tomcat6 Research Fuente: Tomcat mecanismo de carga de clases

En primer lugar nos fijamos en la carga de clases máquina virtual Java mecanismo.
cargador de clases de arranque (para la carga JRE \ lib \ rt.jar Xbootclasspath frasco o paquete especificado)
cargador de clases de extensión (para el directorio de carga extensión estándar / jdk / jre / lib / ext)
cargador de clases del sistema (para cargar los archivos y directorios tarro variable de entorno CLASSPATH o DJava.class.path)
cargador de clases de encargo (cargador de clases definidas por el usuario)
El cargador modelo de delegación de clase para cumplir con ambos padres, cuando la carga de archivos primero se delegan a sus padres cargador carga el cargador de los padres ha sido cargado, entonces el éxito. Si el caso en el que un padre no puede cargar hasta la carga será delegada a un sub-loader de carga.
contenedor Tomcat Servlet define su propio cargador de clases, por dos razones:
Por un lado podemos detenerlo, pero no se puede confiar para cargar otra carrera en una clase de máquina virtual, por lo que puede resolver el problema de seguridad. Tomcat contenedor de servlets sólo puede ser cargada directorio WEB-INF / classes y sus subdirectorios y Ingeniería / lib cabezas de clase, las necesidades que dependen de este cargador WEB-INF para implementar la interfaz org.apache.catalina.Loader.java.

Otro aspecto puede ser un WEB-INF / clases o WEB-INF / lib Los archivos siguientes se cargan automáticamente cuando el cambio, Tomcat se iniciará un hilo para monitorear los cambios en estos dos archivos bajo dichos implementos loader la org.apache interfaz. catalina.loader.Reloader.java. Sí, la depuración local, cuando se modifica el archivo de clase no es necesario reiniciar el gato

Dos archivos de origen de la siguiente manera:

interfaz pública cargador {

    // -------------------------------------------- ----------------- Propiedades

    / **
     * ejecutar una tarea periódica, tales como recarga, etc. este método será
     * invocada dentro del contexto de carga de clases de este contenedor. Inesperados
     * throwables serán capturados y se registran.
     * /
    BackgroundProcess public void ();
    / **
     * Devuelve el cargador de clases de Java para ser utilizado por este contenedor.
     * /
    Público ClassLoader getClassLoader ();
    / **
     * Devuelve el contenedor con la que este cargador se ha asociado.
     * /
    Pública de contenedores getContainer ();
    / **
     * Ajuste el recipiente con el que este cargador se ha asociado.
     *
     * @Param envase El Contenedor asociado
     * /
    setContainer public void (contenedor de contenedores);
    / **
     * Volver la bandera "seguir el modelo estándar de la delegación" se utiliza para configurar
     * nuestro cargador de clases.
     * /
    GetDelegate public boolean ();
    / **
     * Establecer la bandera "seguir el modelo estándar de la delegación" se utiliza para configurar
     * nuestro cargador de clases.
     *
     * @Param delegado La nueva bandera
     * /
    setDelegate public void (delegado booleano);
    / **
     * Retorno información descriptiva acerca de esta implementación de cargador y
     * el número de versión correspondiente, en el formato
     * <code> & lt; description & gt; / & lt; versión & gt; </ code>.
     * /
    Public String getInfo ();
    / **
     * Devuelve la bandera recargable para este cargador.
     * /
    Public boolean getReloadable ();
    / **
     * Establecer el indicador recargable para este cargador.
     *
     * @Param recargable La nueva bandera recargable
     * /
    setReloadable public void (recargable booleano);
    // ------------------------------------------------ --------- Métodos públicos
    / **
     * Añadir un oyente de cambio de propiedad a este componente.
     *
     * @Param oyente El oyente para añadir
     * /
    addPropertyChangeListener public void (PropertyChangeListener oyente);
    / **
     * Añadir un nuevo repositorio para el conjunto de repositorios para este cargador de clases.
     *
     * @Param Repositorio que se añade
     * /
    público addRepository vacío (repositorio de cadena);
    / **
     * Devuelve el conjunto de repositorios definidos para este cargador de clases.
     * Si se definen ninguno, se devuelve una matriz de longitud cero.
     * /
    String [] findRepositories públicas ();
    / **
     * Tiene el repositorio interna asociada con este cargador sido modificado,
     * tal que las clases cargadas deben ser recargados?
     * /
    Public boolean modificado ();
    / **
     * Eliminar un oyente de cambio de propiedad de este componente.
     *
     * @Param oyente El oyente para eliminar
     * /
    removePropertyChangeListener public void (PropertyChangeListener oyente);
}

public interface Reloader {
    /**
     * Add a new repository to the set of places this ClassLoader can look for
     * classes to be loaded.
     *
     * @param repository Name of a source of classes to be loaded, such as a
     *  directory pathname, a JAR file pathname, or a ZIP file pathname
     *
     * @exception IllegalArgumentException if the specified repository is
     *  invalid or does not exist
     */
    public void addRepository(String repository);
    /**
     * Return a String array of the current repositories for this class
     * loader.  If there are no repositories, a zero-length array is
     * returned.
     */
    public String[] findRepositories();

    /**
     * Have one or more classes or resources been modified so that a reload
     * is appropriate?
     */
    public boolean modified();
}
tomcat类加载器的UML图如下
先来看看WebappLoader.java,它创建了一个WebappClassLoader的实例作为自己的类加载器。它实现了Loader.java接口,并且跟其他catalina组件一样,也实现了 org.apache.catalina.Lifecycle接口以便能被其他容器打开和关闭。同时也实现了java.beans.PropertyChangeListener接口,当属性改变时通知相关容器。而WebappLoader本身的重启是由Context(tomcat的容器)来控制的。
WebappLoader的启动的时候会发生下面几个工作:
如果没有初始化,则初始化并且注册容器;如果是第一次初始化,为JNDI注册流处理器;创建类加载器;设置repository;设置classpath;设置权限;为目录绑定类加载器。
public void start() throws LifecycleException {
        // Validate and update our current component state
        if( ! initialized ) init();
        if (started)
            throw new LifecycleException
                (sm.getString("webappLoader.alreadyStarted"));
        if (log.isDebugEnabled())
            log.debug(sm.getString("webappLoader.starting"));
        lifecycle.fireLifecycleEvent(START_EVENT, null);
        started = true;

        if (container.getResources() == null) {
            log.info("No resources for " + container);
            return;
        }
        // Register a stream handler factory for the JNDI protocol
        URLStreamHandlerFactory streamHandlerFactory =
            new DirContextURLStreamHandlerFactory();
        if (first) {
            first = false;
            try {
                URL.setURLStreamHandlerFactory(streamHandlerFactory);
            } catch (Exception e) {
                // Log and continue anyway, this is not critical
                log.error("Error registering jndi stream handler", e);
            } catch (Throwable t) {
                // This is likely a dual registration
                log.info("Dual registration of jndi stream handler: " 
                         + t.getMessage());
            }
        }

        // Construct a class loader based on our current repositories list
        try {
            classLoader = createClassLoader();
            classLoader.setResources(container.getResources());
            classLoader.setDelegate(this.delegate);
            if (container instanceof StandardContext)
                classLoader.setAntiJARLocking(((StandardContext) container).getAntiJARLocking());

            for (int i = 0; i < repositories.length; i++) {
                classLoader.addRepository(repositories[i]);
            }

            // Configure our repositories
            setRepositories();
            setClassPath();
            setPermissions();

            if (classLoader instanceof Lifecycle)
                ((Lifecycle) classLoader).start();

            // Binding the Webapp class loader to the directory context
            DirContextURLStreamHandler.bind
                ((ClassLoader) classLoader, this.container.getResources());

            StandardContext ctx=(StandardContext)container;
            Engine eng=(Engine)ctx.getParent().getParent();
            String path = ctx.getPath();
            if (path.equals("")) {
                path = "/";
            }   
            ObjectName cloname = new ObjectName
                (ctx.getEngineName() + ":type=WebappClassLoader,path="
                 + path + ",host=" + ctx.getParent().getName());
            Registry.getRegistry(null, null)
                .registerComponent(classLoader, cloname, null);

        } catch (Throwable t) {
            log.error( "LifecycleException ", t );
            throw new LifecycleException("start: ", t);
        }
    }


发布了34 篇原创文章 · 获赞 2 · 访问量 4万+

Supongo que te gusta

Origin blog.csdn.net/zjj2006/article/details/17509447
Recomendado
Clasificación