`
zhaohaolin
  • 浏览: 1012693 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

tomcat 7 源码分析-2 类加载ClassLoader

阅读更多

tomcat 7 源码分析-2 类加载ClassLoader

 

tomcat在启动的时候使用了三个类加载器

 

Java代码  收藏代码
  1. private   void  initClassLoaders() {  
  2.     try  {  
  3.         commonLoader = createClassLoader("common" null );  
  4.         if ( commonLoader ==  null  ) {  
  5.             // no config file, default to this loader - we might be in a 'single' env.   
  6.             commonLoader=this .getClass().getClassLoader();  
  7.         }  
  8.         catalinaLoader = createClassLoader("server" , commonLoader);  
  9.         sharedLoader = createClassLoader("shared" , commonLoader);  
  10.     } catch  (Throwable t) {  
  11.         log.error("Class loader creation threw exception" , t);  
  12.         System.exit(1 );  
  13.     }  
  14. }  
    private void initClassLoaders() {
        try {
            commonLoader = createClassLoader("common", null);
            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);
            sharedLoader = createClassLoader("shared", commonLoader);
        } catch (Throwable t) {
            log.error("Class loader creation threw exception", t);
            System.exit(1);
        }
    }

 三个类加载器加载了catalina.properties中的jar

 

Java代码  收藏代码
  1. common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar  
  2. server.loader=  
  3. shared.loader=  
common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar
server.loader=
shared.loader=

 由此可见三个类加载器加载的jar是一样的。为什么要用三个类加载器,从名称看应该是有分别的作用考虑,负载的考虑也许吧。

此外    private ClassLoader createClassLoader(String name, ClassLoader parent)中调用        ClassLoader classLoader = ClassLoaderFactory.createClassLoader

            (locations, types, parent);

tomcat自定义了一个类加载器,并且定义了ClassLoaderFactory根据参数定义返回classloader。总体上ClassLoaderFactory就是根据catalina.properties中的jar的位置,做了一些字符串的处理。

 

Java代码  收藏代码
  1. public   static  ClassLoader createClassLoader(String locations[],  
  2.                                                 Integer types[],  
  3.                                                 ClassLoader parent)  
  4.         throws  Exception {  
  5.   
  6.         if  (log.isDebugEnabled())  
  7.             log.debug("Creating new class loader" );  
  8.   
  9.         // Construct the "class path" for this class loader   
  10.         Set<URL> set = new  LinkedHashSet<URL>();  
  11.   
  12.         if  (locations !=  null  && types !=  null  && locations.length == types.length) {  
  13.             for  ( int  i =  0 ; i < locations.length; i++)  {  
  14.                 String location = locations[i];  
  15.                 if  ( types[i] == IS_URL ) {  
  16.                     URL url = new  URL(location);  
  17.                     if  (log.isDebugEnabled())  
  18.                         log.debug("  Including URL "  + url);  
  19.                     set.add(url);  
  20.                 } else   if  ( types[i] == IS_DIR ) {  
  21.                     File directory = new  File(location);  
  22.                     directory = new  File(directory.getCanonicalPath());  
  23.                     if  (!directory.exists() || !directory.isDirectory() ||  
  24.                         !directory.canRead())  
  25.                          continue ;  
  26.                     URL url = directory.toURI().toURL();  
  27.                     if  (log.isDebugEnabled())  
  28.                         log.debug("  Including directory "  + url);  
  29.                     set.add(url);  
  30.                 } else   if  ( types[i] == IS_JAR ) {  
  31.                     File file=new  File(location);  
  32.                     file = new  File(file.getCanonicalPath());  
  33.                     if  (!file.exists() || !file.canRead())  
  34.                         continue ;  
  35.                     URL url = file.toURI().toURL();  
  36.                     if  (log.isDebugEnabled())  
  37.                         log.debug("  Including jar file "  + url);  
  38.                     set.add(url);  
  39.                 } else   if  ( types[i] == IS_GLOB ) {  
  40.                     File directory=new  File(location);  
  41.                     if  (!directory.exists() || !directory.isDirectory() ||  
  42.                         !directory.canRead())  
  43.                         continue ;  
  44.                     if  (log.isDebugEnabled())  
  45.                         log.debug("  Including directory glob "   
  46.                             + directory.getAbsolutePath());  
  47.                     String filenames[] = directory.list();  
  48.                     for  ( int  j =  0 ; j < filenames.length; j++) {  
  49.                         String filename = filenames[j].toLowerCase(Locale.ENGLISH);  
  50.                         if  (!filename.endsWith( ".jar" ))  
  51.                             continue ;  
  52.                         File file = new  File(directory, filenames[j]);  
  53.                         file = new  File(file.getCanonicalPath());  
  54.                         if  (!file.exists() || !file.canRead())  
  55.                             continue ;  
  56.                         if  (log.isDebugEnabled())  
  57.                             log.debug("    Including glob jar file "   
  58.                                 + file.getAbsolutePath());  
  59.                         URL url = file.toURI().toURL();  
  60.                         set.add(url);  
  61.                     }  
  62.                 }  
  63.             }  
  64.         }  
  65.   
  66.         // Construct the class loader itself   
  67.         URL[] array = set.toArray(new  URL[set.size()]);  
  68.         if  (log.isDebugEnabled())  
  69.             for  ( int  i =  0 ; i < array.length; i++) {  
  70.                 log.debug("  location "  + i +  " is "  + array[i]);  
  71.             }  
  72.         StandardClassLoader classLoader = null ;  
  73.         if  (parent ==  null )  
  74.             classLoader = new  StandardClassLoader(array);  
  75.         else   
  76.             classLoader = new  StandardClassLoader(array, parent);  
  77.         return  (classLoader);  
  78.   
  79.     }  
public static ClassLoader createClassLoader(String locations[],
                                                Integer types[],
                                                ClassLoader parent)
        throws Exception {

        if (log.isDebugEnabled())
            log.debug("Creating new class loader");

        // Construct the "class path" for this class loader
        Set<URL> set = new LinkedHashSet<URL>();

        if (locations != null && types != null && locations.length == types.length) {
            for (int i = 0; i < locations.length; i++)  {
                String location = locations[i];
                if ( types[i] == IS_URL ) {
                    URL url = new URL(location);
                    if (log.isDebugEnabled())
                        log.debug("  Including URL " + url);
                    set.add(url);
                } else if ( types[i] == IS_DIR ) {
                    File directory = new File(location);
                    directory = new File(directory.getCanonicalPath());
                    if (!directory.exists() || !directory.isDirectory() ||
                        !directory.canRead())
                         continue;
                    URL url = directory.toURI().toURL();
                    if (log.isDebugEnabled())
                        log.debug("  Including directory " + url);
                    set.add(url);
                } else if ( types[i] == IS_JAR ) {
                    File file=new File(location);
                    file = new File(file.getCanonicalPath());
                    if (!file.exists() || !file.canRead())
                        continue;
                    URL url = file.toURI().toURL();
                    if (log.isDebugEnabled())
                        log.debug("  Including jar file " + url);
                    set.add(url);
                } else if ( types[i] == IS_GLOB ) {
                    File directory=new File(location);
                    if (!directory.exists() || !directory.isDirectory() ||
                        !directory.canRead())
                        continue;
                    if (log.isDebugEnabled())
                        log.debug("  Including directory glob "
                            + directory.getAbsolutePath());
                    String filenames[] = directory.list();
                    for (int j = 0; j < filenames.length; j++) {
                        String filename = filenames[j].toLowerCase(Locale.ENGLISH);
                        if (!filename.endsWith(".jar"))
                            continue;
                        File file = new File(directory, filenames[j]);
                        file = new File(file.getCanonicalPath());
                        if (!file.exists() || !file.canRead())
                            continue;
                        if (log.isDebugEnabled())
                            log.debug("    Including glob jar file "
                                + file.getAbsolutePath());
                        URL url = file.toURI().toURL();
                        set.add(url);
                    }
                }
            }
        }

        // Construct the class loader itself
        URL[] array = set.toArray(new URL[set.size()]);
        if (log.isDebugEnabled())
            for (int i = 0; i < array.length; i++) {
                log.debug("  location " + i + " is " + array[i]);
            }
        StandardClassLoader classLoader = null;
        if (parent == null)
            classLoader = new StandardClassLoader(array);
        else
            classLoader = new StandardClassLoader(array, parent);
        return (classLoader);

    }

 定义了类加载器后,在init()中加载

 

Java代码  收藏代码
  1. Class<?> startupClass =  
  2.     catalinaLoader.loadClass  
  3.     ("org.apache.catalina.startup.Catalina" );  
        Class<?> startupClass =
            catalinaLoader.loadClass
            ("org.apache.catalina.startup.Catalina");

 这个才是tomcat的守护进程。

 

Java代码  收藏代码
  1. Thread.currentThread().setContextClassLoader(catalinaLoader);  
  2.   
  3.  SecurityClassLoad.securityClassLoad(catalinaLoader);  
  4.   
  5.  // Load our startup class and call its process() method   
  6.  if  (log.isDebugEnabled())  
  7.      log.debug("Loading startup class" );  
  8.  Class<?> startupClass =  
  9.      catalinaLoader.loadClass  
  10.      ("org.apache.catalina.startup.Catalina" );  
  11.  Object startupInstance = startupClass.newInstance();          
  12.  // Set the shared extensions class loader   
  13.  if  (log.isDebugEnabled())  
  14.      log.debug("Setting startup class properties" );  
  15.  String methodName = "setParentClassLoader" ;  
  16.  Class<?> paramTypes[] = new  Class[ 1 ];  
  17.  paramTypes[0 ] = Class.forName( "java.lang.ClassLoader" );  
  18.  Object paramValues[] = new  Object[ 1 ];  
  19.  paramValues[0 ] = sharedLoader;  
  20.  Method method =  
  21.      startupInstance.getClass().getMethod(methodName, paramTypes);  
  22.  method.invoke(startupInstance, paramValues);  
  23.  catalinaDaemon = startupInstance;  
       Thread.currentThread().setContextClassLoader(catalinaLoader);

        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;

 这里要说的是

 

Class.forName()和ClassLoader.loadClass()的区别?

这两个方法由给类名作为参数,动态的定位并且加载类。然而,两者行为的区别在于用哪个加载器(java.lang.ClassLoader)去加载和加载完后的类是否就已经初始化。

对于Class.forName()最常见的形式就是用一个单独的String为参数,使用当前调用者的类加载器。这个类加载器加载代码执行 forName()方法。比较ClassLoader.loadClass(),它是一个实例方法,需要你去选择确定的classloader。这个类加 载器可以是也可以不是当前加载器。如果选择一个特定的类加载器对你的设计尤为重要,你可以使用ClassLoader.loadClass()或者三个参 数的forName()。

更进一步,Class.forName()的常见形式会初始化加载的类。这样做的就是执行了类的静态初始化方法,也就是byte代码对应的所有静态 初始化表达式。这和ClassLoader.loadClass()是不同的,ClassLoader.loadClass()直到类第一次使用的时候才 初始化。

分享到:
评论

相关推荐

    apache-tomcat-7.0.81-src 源码免费下载

    Apache Tomcat 7.0.81 源码分析 Apache Tomcat 是一个流行的开源软件,用Java语言编写,是实现Java Servlet和JavaServer Pages(JSP)规范的应用服务器,广泛用于Web应用的开发和部署。源码的下载对于开发者来说...

    apache-tomcat-源码-lib包

    4. **类加载器**:Tomcat使用自定义的类加载器来加载Web应用的类,这使得不同应用之间的类可以隔离,避免冲突。源码中,ClassLoader的实现(例如`org.apache.catalina.loader.WebappClassLoaderBase`)值得深入研究...

    java类加载器-tomcat中的类加载器

    2. Webapp ClassLoader:每个Web应用程序都有自己的Webapp ClassLoader,用于加载WEB-INF/classes和WEB-INF/lib下的类,遵循"父子优先"原则,优先尝试从父类加载器加载,如果找不到再从自身加载。 3. Shared ...

    Tomcat7 源码Eclipse工程

    Tomcat7源码还涉及到了类加载机制,它采用了自定义的类加载器,如`CatalinaClassLoader`和`SharedClassLoader`,理解这些类加载器的工作方式有助于解决类冲突和加载顺序问题。 此外,Tomcat的安全管理也是重要一环...

    Tomcat 5.0.18 ClassLoader source code insight

    通过对Tomcat 5.0.18 ClassLoader的源码分析,我们可以更好地理解和控制应用的类加载行为,这对于解决类冲突、优化性能和提高安全性都至关重要。在实际开发中,理解这些细节可以帮助我们更高效地部署和调试Java Web...

    Tomcat6的源码

    5. **ClassLoader机制**:Tomcat的类加载机制允许每个Web应用拥有自己的类加载器,避免类冲突。理解这部分源码对于理解和解决部署问题至关重要。 6. **Session管理**:Tomcat处理用户会话,包括创建、跟踪和管理...

    Tomcat:apache-tomcat-6.0.18

    5. **ClassLoader机制**:Tomcat使用自定义的ClassLoader来加载Web应用程序的类,确保不同应用之间的类隔离,防止冲突。 Tomcat 6.0.18版的特性包括: 1. **性能优化**:相对于之前的版本,6.0.18进行了性能调优,...

    tomcat8源码的maven项目

    在这个项目中,开发者可能已经配置了相关的Maven插件和目标,以便于编译、测试和打包Tomcat源码。 【标签】: 1. **Tomcat8**:Tomcat 8是Tomcat服务器的第8个主要版本,它支持Java Servlet 3.1、JavaServer Pages...

    TOMCAT源代码,包括转载得别人的分析

    通过阅读"TOMCAT源码分析.doc"和解压后的"apache-tomcat-6.0.0-src.zip",你可以深入了解上述知识点,并学习如何根据源码进行调试、优化或扩展Tomcat。这份资料对于Java Web开发者来说是一份宝贵的参考资料,有助于...

    tomcat8源码

    Tomcat使用自定义的ClassLoader来加载Web应用的类,这使得每个应用可以有自己的类空间,避免类冲突。Classloading策略是理解和调试Tomcat应用的重要部分。 7. **Session管理** Tomcat提供了会话管理机制,包括...

    tomcat-4.1.40-src

    3. **启动流程**:Tomcat的启动过程始于`bin/catalina.sh`或`catalina.bat`,这些脚本会初始化Java环境,并加载`catalina.jar`中的`org.apache.catalina.startup.ClassLoader`,接着加载`Server`对象,初始化`...

    tomcat 6 源码

    5. **ClassLoader**:Tomcat使用自定义的ClassLoader来加载Web应用的类。这使得不同应用之间能隔离地运行,避免类冲突。 6. **Lifecycle**:所有Tomcat组件都遵循生命周期接口,如`org.apache.catalina.Lifecycle`...

    apache-tomcat-9.0.11源码

    了解并研究Tomcat源码对于深入理解Web服务器的工作原理,优化应用程序性能,以及解决可能出现的技术问题都具有重要意义。 1. **Servlet与JSP**: - **Servlet**:Servlet是Java编程语言中的一个接口,它定义了Web...

    细说Tomcat如何打破双亲委派(有源码和图)

    本篇文章将深入探讨Tomcat如何打破双亲委派模型,并通过源码分析和图表解析来帮助理解这一机制。 首先,我们需要了解Java的双亲委派模型。这个模型是由JDK中的ClassLoader实现的,默认情况下,当一个类加载器需要...

Global site tag (gtag.js) - Google Analytics