2011-06-06 160 views
16

Tomcat的Class Loader HOW-TO文档描述4个不同的类加载器:顺序:普通,共享和服务器

  1. 引导
  2. 系统
  3. 的webapp
  4. 普通

在但是,默认的catalina.properties文件也有为共享和服务器类加载器定义的属性。在该文件的默认版本的这两个属性是空的,评论说:

如果留为空白,“常用”装载机 将用作Catalina的 “共享” /“服务器”装载机。

我一直没能找到关于这些类加载器的任何其他文档。我的问题是,共享加载程序和系统加载程序按照什么顺序搜索?另外,这些类装载机的预期用途是什么?

+0

另请参见http://stackoverflow.com/questions/5474765/order-of-loading-jar-files-from-lib-directory – rogerdpack 2014-09-26 17:50:30

回答

9

我最近就遇到了这个问题,也是在这里是我发现,(这是所有从Tomcat 7主干)

首先,If left as blank, the "common" loader will be used as Catalina's "shared"/"server" loader.

下面是相关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类加载器,然后行251套shared.loader classloader被设置为Catalinas父类加载器。

1

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

我们确实使用共享加载器广泛地覆盖我们的软件的香草版本随附的现有类。我们制作的软件来自发行版,并且为一个客户制作完整的新版本(这需要一个关键的bug修复)太昂贵了(重新测试一切,重建,提供新文档,新版本号等等)。因此,我们所做的是提供一个“修补程序”,它将进入共享加载程序并覆盖webapp中的相关.class

大多数情况下,“hotfix”只是一个类,所以整体回归风险很小。

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

我也可以想象其他人使用共享类加载器来产生跨越许多不同webapps的东西。

+1

所以,@ mindas,你说共享类加载器实际上是之前搜索webapp类加载器?这看起来不正确。 – 2011-06-06 23:34:11

1

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

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