Tomcat类加载器的顺序:公共、共享和服务器

Tomcat类加载器的顺序:公共、共享和服务器,tomcat,configuration,classloader,Tomcat,Configuration,Classloader,Tomcat文档描述了4种不同的类装入器: 引导 系统 普通的 网络应用 但是,在默认的catalina.properties文件中,也为共享和服务器类加载器定义了属性。在文件的默认版本中,这两个属性都是空的,注释显示: 如果保留为空,“公共”加载程序 将用作Catalina的 “共享”/“服务器”加载程序 我还没有找到关于这些类装入器的任何其他文档。我的问题是,相对于公共加载程序,共享加载程序和系统加载程序的搜索顺序是什么?此外,这些类加载器的预期用途是什么?奇怪的是,仍然有共享的加载器,但是

Tomcat文档描述了4种不同的类装入器:

  • 引导
  • 系统
  • 普通的
  • 网络应用
  • 但是,在默认的catalina.properties文件中,也为共享和服务器类加载器定义了属性。在文件的默认版本中,这两个属性都是空的,注释显示:

    如果保留为空,“公共”加载程序 将用作Catalina的 “共享”/“服务器”加载程序

    我还没有找到关于这些类装入器的任何其他文档。我的问题是,相对于公共加载程序,共享加载程序和系统加载程序的搜索顺序是什么?此外,这些类加载器的预期用途是什么?

    奇怪的是,仍然有
    共享的
    加载器,但是;您引用的v7.0也没有。也许他们会反对它

    我们确实广泛使用共享加载器来覆盖现有的类,这些类随我们的软件的普通版本而来。我们制作的软件都是发布版本,为一个客户制作一个完整的新版本(比如说,需要一个关键的错误修复)成本太高(重新测试所有内容、重建、提供新文档、新版本号等)。因此,我们所做的是提供一个“修补程序”,它进入共享加载程序并覆盖webapp中的相关
    .class

    大多数情况下,“修补程序”只是一个类,因此总体回归风险最小

    当我们的软件升级时,升级将删除“修补程序”,因为更正后的代码也将出现在下一版本的软件中


    我还可以想象其他人使用共享类加载器来实现许多不同的Web应用程序。

    我最近也遇到了这个问题,下面是我的发现(这些都来自Tomcat 7 trunk)

    如果留空,“公共”加载程序将用作Catalina的“共享”/“服务器”加载程序

    这是相关的,

    因此,如果未定义任何内容,它们将退回到使用common.loader条目


    至于装载的顺序, 这是从中加载它们的源代码

    229 Thread.currentThread().setContextClassLoader(CatalinalLoader);
    230
    231 SecurityClassLoad.SecurityClassLoad(CatalinalLoader);
    232
    233//加载启动类并调用其process()方法
    234如果(log.isDebugEnabled())
    235 log.debug(“加载启动类”);
    236班=
    237 CatalinalLoader.loadClass
    238(“org.apache.catalina.startup.catalina”);
    239 Object startupInstance=startupClass.newInstance();
    240
    241//设置共享扩展类加载器
    242如果(log.isDebugEnabled())
    243 log.debug(“设置启动类属性”);
    244 String methodName=“setParentClassLoader”;
    245类参数类型[]=新类[1];
    246 paramTypes[0]=Class.forName(“java.lang.ClassLoader”);
    247对象参数值[]=新对象[1];
    248参数值[0]=共享加载程序;
    249方法=
    250 startupInstance.getClass().getMethod(方法名,参数类型);
    251方法。调用(startupInstance,paramValues);
    

    第229行设置common.loader类加载器,然后第251行设置shared.loader类加载器被设置为Catalinas父类加载器。

    同意mindas的观点,apache tomcat group可能正在考虑弃用服务器和共享类加载器。关于webappclassloader和standardclassloader(common class loader)的顺序,有一篇由Jianbo撰写的有趣的文章。他做了一个简单的测试来证明这一点


    基本上,它的要点是,在tomcat中,类加载器首先从webapp加载类,然后是共享/公共,然后是系统。

    那么,@mindas,你是说共享类加载器实际上是在webapp类加载器之前搜索的?这似乎不对。请看链接现在已经死了。谢谢@Hearen,修复了链接。
    89      private void initClassLoaders() {
    90          try {
    91              commonLoader = createClassLoader("common", null);
    92              if( commonLoader == null ) {
    93                  // no config file, default to this loader - we might be in a 'single' env.
    94                  commonLoader=this.getClass().getClassLoader();
    95              }
    96              catalinaLoader = createClassLoader("server", commonLoader);
    97              sharedLoader = createClassLoader("shared", commonLoader);
    98          } catch (Throwable t) {
    99              handleThrowable(t);
    100             log.error("Class loader creation threw exception", t);
    101             System.exit(1);
    102         }
    103     }
    
    106     private ClassLoader createClassLoader(String name, ClassLoader parent)
    107         throws Exception {
    108 
    109         String value = CatalinaProperties.getProperty(name + ".loader");
    110         if ((value == null) || (value.equals("")))
    111             return parent;
    
    229         Thread.currentThread().setContextClassLoader(catalinaLoader);
    230 
    231         SecurityClassLoad.securityClassLoad(catalinaLoader);
    232 
    233         // Load our startup class and call its process() method
    234         if (log.isDebugEnabled())
    235             log.debug("Loading startup class");
    236         Class<?> startupClass =
    237             catalinaLoader.loadClass
    238             ("org.apache.catalina.startup.Catalina");
    239         Object startupInstance = startupClass.newInstance();
    240 
    241         // Set the shared extensions class loader
    242         if (log.isDebugEnabled())
    243             log.debug("Setting startup class properties");
    244         String methodName = "setParentClassLoader";
    245         Class<?> paramTypes[] = new Class[1];
    246         paramTypes[0] = Class.forName("java.lang.ClassLoader");
    247         Object paramValues[] = new Object[1];
    248         paramValues[0] = sharedLoader;
    249         Method method =
    250             startupInstance.getClass().getMethod(methodName, paramTypes);
    251         method.invoke(startupInstance, paramValues);