Tomcat类加载器的顺序:通用,共享和服务器

时间:2011-06-06 16:09:09

标签: tomcat configuration classloader

Tomcat Class Loader HOW-TO文档描述了4种不同的类加载器:

  1. 自举
  2. 系统
  3. 通用
  4. 的webapp
  5. 但是,在默认的catalina.properties文件中,还为共享和服务器类加载器定义了属性。在文件的默认版本中,这两个属性都是空的,注释说:

      

    如果留空,则为“常用”装载程序   将用作Catalina的   “共享”/“服务器”加载程序。

    我无法找到有关这些类加载器的任何其他文档。我的问题是,共享和系统加载器相对于公共加载器的搜索顺序是什么?另外,这些类加载器的用途是什么?

3 个答案:

答案 0 :(得分:10)

我最近遇到了这个问题,这是我发现的,(这都是来自Tomcat 7主干)

  

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

以下是相关的source

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;

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


关于加载它们的顺序, 这是从source

加载它们的来源
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);

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

答案 1 :(得分:1)

奇怪,Tomcat 5.5 classloader doc仍然记录了shared加载程序,但6.0 doesn't;你引用的v7.0都没有。也许他们会弃用它?

我们广泛使用共享加载程序 来覆盖我们软件的vanilla版本附带的现有类。我们制作的软件包含在发行版中,并为一个客户制作一个完整的新版本(例如,需要一个关键的错误修复)太昂贵(重新测试所有内容,重建,提供新文档,新版本号等)。所以我们做的是我们提供一个“修补程序”,它进入共享加载程序并覆盖webapp中相关的.class

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

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

我还可以想象其他人使用共享类加载器来生成许多不同的webapps。

答案 2 :(得分:1)

同意mindas,apache tomcat group可能正在考虑弃用服务器和共享类加载器。关于webappclassloader和standardclassloader(通用类加载器)的顺序,Jianbo有一个有趣的帖子。他做了一个简单的测试来证明它。 http://web.archive.org/web/20120303091507/http://www.jianbozhu.net/2012/02/14/tomcat-classloader-demonstration/

基本上,它的主旨是在tomcat中,类加载器首先从webapp加载类,然后是shared / common,然后加载系统。