Tomcat 之 ClassLoader

Classloader

参考:http://www.iteye.com/topic/83978

            http://longdick.iteye.com/blog/442213

1,作用:

它就是用来加载Class文件到JVM,以供程序使用。所有java class 加载过程从此开始。

2,实现:

最上级的Classloader是由C++编写,名叫:bootstrap classloader。jvm运行后,bootstrap classloader被启动,驻留在内存中,供程序调用,进行类加载。

这个ClassLoader在JVM运行的时候加载java核心的API以满足java程序最基本的需求。

3,应用程序中ClassLoader层级关系

jvm默认ClassLoader分3个: 

     Bootstrap ClassLoader负责加载java基础类,主要是 %JRE_HOME/lib/ 目录下的rt.jar、resources.jar、harsets.jar和class等

     Extension ClassLoader负责加载java扩展类,主要是 %JRE_HOME/lib/ext 目录下的jar和class

     App ClassLoader负责加载当前java应用的classpath中的所有类。

ClassLoader调用顺序如下:


注意:这里的层级并不是基础关系。

一、ClassLoader具体实现机制:双亲委托模式

    ClassLoader这个抽象类中有一个getParent()方法,并且有一个parent 变量。

    看代码如下:

 protected synchronized Class loadClass(String name, boolean resolve)  
   throws ClassNotFoundException  
   {  
     // 首先检查该name指定的class是否有被加载  
    Class c = findLoadedClass(name);  
    if (c == null) {  
    try {  
    if (parent != null) {  
        //如果parent不为null,则调用parent的loadClass进行加载  
         = parent.loadClass(name, false);  
    } else {  
        //parent为null,则调用BootstrapClassLoader进行加载  
        c = findBootstrapClass0(name);  
    }  
    } catch (ClassNotFoundException e) {  
        //如果仍然无法加载成功,则调用自身的findClass进行加载              
        c = findClass(name);  
    }  
}  
  if (resolve) {  
    resolveClass(c);  
 }  
   return c;  
   }  

每个ClassLoader都会有它上一级的ClassLoader(boost 除外),当加载类的时候,会首先调用Parent ClassLoader进行加载,如果parent还有上一级,则再调用上一级parent进行加载。总之,最后一级parent一定是 Bootstrap ClassLoader 。所以就确保了总是优先调用Bootstrap ClassLoader 进行类加载。然后再下一级下一级。。

Tomcat ClassLoader实现:

  每个运行中的线程都有一个成员contextClassLoader,用来在运行时动态地载入其它类。系统默认的contextClassLoader是systemClassLoader,所以一般而言java程序在执行时可以使用JVM自带的类、$JAVA_HOME/jre/lib/ext/中的类和$CLASSPATH/中的类。可以使用Thread.currentThread().setContextClassLoader(...);更改当前线程的contextClassLoader,来改变其载入类的行为,但是最终都会调用systemClassLoader。

现在看Tomcat 启动过程:

在startup.bat调用catalina.bat ,bat文件中找到启动类:

set _EXECJAVA=%_RUNJAVA%
set MAINCLASS=org.apache.catalina.startup.Bootstrap

Bootstrap启动类中

1,初始化函数:init()

   public void init()
        throws Exception
    {

        // Set Catalina path
        setCatalinaHome();
        setCatalinaBase();

        initClassLoaders();//初始化ClassLoader

        Thread.currentThread().setContextClassLoader(catalinaLoader);设置当前线程ClassLoader

        SecurityClassLoad.securityClassLoad(catalinaLoader);

        // Load our startup class and call its process() method
        if (log.isDebugEnabled())
            log.debug("Loading startup class");
        Class startupClass =
            catalinaLoader.loadClass
            ("org.apache.catalina.startup.Catalina");
        Object startupInstance = startupClass.newInstance();

        // Set the shared extensions class loader
        if (log.isDebugEnabled())
            log.debug("Setting startup class properties");
        String methodName = "setParentClassLoader";
        Class paramTypes[] = new Class[1];
        paramTypes[0] = Class.forName("java.lang.ClassLoader");
        Object paramValues[] = new Object[1];
        paramValues[0] = sharedLoader;
        Method method =
            startupInstance.getClass().getMethod(methodName, paramTypes);
        method.invoke(startupInstance, paramValues);

        catalinaDaemon = startupInstance;

    }
其中initClassLoader()函数如下:


    private void initClassLoaders() {
        try {
            commonLoader = createClassLoader("common", null);  //common ---system loader
            if( commonLoader == null ) {
                // no config file, default to this loader - we might be in a 'single' env.
                commonLoader=this.getClass().getClassLoader();
            }
            catalinaLoader = createClassLoader("server", commonLoader); //Tomcat classLoader
            sharedLoader = createClassLoader("shared", commonLoader);//Webapp classloader 
        } catch (Throwable t) {
            log.error("Class loader creation threw exception", t);
            System.exit(1);
        }
    }

可以看出:

1,当前线程设置的ClassLoader 是 CatalinaLoader。

2,初始化了3个classloader:commonloader、catalinaloader、sharedloader

    其中catalinaloader、sharedloader的parent  loader 是commonloader。

    它们作用如下:

    --commonloader

       这个目录下的类虽然对TOMCAT和所有的WEB APP都可见.但是Web App的类不应该 放在这个目录下,所有未打包的Class都在$CATALINA_HOME/common/classes下,所 有打包的jar都在 $CATALINA_HOME/commons/endorsed $CATALINA_HOME/common/lib下。

默认情况包含如下几个包(现在版本已不是这样,学习用):

1. naming-common.jar JNDI接口实现类,Tomcat用这些类在内存中使用Context. 
2. naming-resources.jar JNDI实现,Tomcat用它们定位Web App的静态资源. 
3. servlet.jar Servlet,Jsp API 
4. xerces.jar XML解析器,特定的Web App可以在自己的/WEB-INF/lib 中覆盖. 

    -catalinaloader

默认包含下面几个包(现在版本已不是这样,学习用

                 1. catalina.jar Servlet容器的Tomcat实现包 
                    2. jakarta-regexp-X.Y.jar 正则表达式,请求过滤时使用 
                    3. servlets-xxxxx.jar Servlet支持包 
                    4. tomcat-coyote.jar Tomcat的Coyote连接实现包 
                    5. tomcat-jk.jar Web Server绑定包,允许Tomcat绑定Apache等作为Web Server 
                 6. tomcat-jk2.jar 功能同上 
                    7. tomcat-util.jar Tomcat工具类,可能被一些Connector用到 
                    8. tomcat-warp.jar 用于Apache Server包 

      装入Tomcat实现所有接口的类。这些类对Web App是完全不可见的,所有未打包的类在 $CATALINA_HOME/server/classes所有jar包在$CATALINA_HOME/server/lib下。

   -sharedloader

默认包含下面几个包(现在版本已不是这样,学习用)

1. jasper-compiler.jar Jsp编译器,编译Jsp为Servlet 
2. jasper-runtime.jar Jsp(已编译成Servlet)运行支持包 
3. naming-factory.jar 支持Web App使用JNDI的封装包

       载入所有WEB APP都可见的类,对TOMCAT不可见. 所有未打包的类在  $CATALINA_HOME/shared/classes,所有jar包在$CATALINA_HOME /lib下。

  

再看上面调用的createClassLoader函数:

 private ClassLoader createClassLoader(String name, ClassLoader parent)
        throws Exception {

	。。。。。 
        ClassLoader classLoader = ClassLoaderFactory.createClassLoader
            (locations, types, parent);

	。。。。。
        return classLoader;

    }
调用了ClassLoaderFactory 工厂类来创建ClassLoader。

在ClassLoaderFactory 的createClassLoader()函数中:

        StandardClassLoader classLoader = null;
        if (parent == null)
            classLoader = new StandardClassLoader(array);
        else
            classLoader = new StandardClassLoader(array, parent);
        return (classLoader);

parent就是上面传递的commLoader 。

standardClassLoader是URLClassloader的子类 
(URLClassloader是java.security.SecureClassLoader的子类,java.security.SecureClassLoader 
是Classloader的子类  java.security.SecureClassLoader扩展了Classloader,他还可以支持使用相关的代码源和权限定义类) 。







     


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值