1、Tomcat解析之初始化类加载器(截图)全部 Hibernate Spring Struts iBATIS 企业应用 Lucene SOA Java综合 设计模式 Tomcat OO JBoss 上一页 1 2 下一页 浏览 7744 次锁定老帖子 主题:Tomcat 解析之初始化类加载器(截图)该帖已经被评为精华帖作者 正文 gogole_09 等级: 性别: 文章: 213 积分: 420 来自: 杭州 发表时间:2010-01-30 最后修改:2010-02-01 猎头职位: 上海: 【上海】外资企业高新诚聘 web开发工程师 相关文章: Tomcat 5.5.26源代码分析启动过程(二
2、) Tomcat 源代码分析之 ClassLoader How Tomcat Works翻译(7) 之 Tomcat 类加载器续集 推荐群组: Tapestry 更多相关推荐 Java综合 之前有写过关于 tomcat中常用的一些类结构的文章。解析 Tomcat之 HttpServlet(截图记录) 今天来关注一下,tomcat 的类加载器相关的内容。PS: 由于前一篇文章内容比较简单, 有朋友冠以我标题党之嫌,对于此种说法,本人深感抱歉,可能标题确实有点大,但是这些常用的类,我更多的时候只关注其用法,而忽略了内部实现,所以也就把这些内容总结了一下,发了出来。别无标题党之意,请各位 eyer海
3、涵。OK, 现在进入正题. Tomcat 类加载器初始化.开始之前,我们首先需要了解一下几个基本的知识点; 锁定老帖子 主题:Tomcat 解析之初始化类加载器(截图)该帖已经被评为精华帖作者 正文 1.tomcat中类加载器的结构与关系。 这里,我引用 tomcat文档的一个简图来说明一下, 有兴趣深究的朋友,可以去翻看 tomcat的文档,理解更多信息.锁定老帖子 主题:Tomcat 解析之初始化类加载器(截图)该帖已经被评为精华帖作者 正文 (tomcat5.5)(由于参考的是 tomcat6.0的源代码,这里纠正一下类加载器的图(如下),以免给别的朋友造成误解,同时也多谢 asiale
4、e给出的提醒)(tomcat6.0)2.每种类加载器分别加载什么资源: 这些内容,可以在 tomcat文档的 Class Loader HOW-TO 找到. 这里我要说明的是, 在 tomcat中,这些内容是记录在哪里的。既(程序怎么让 tomcat知道,需要加载哪些类)答案是-其通过一个配置文件来指定的:(catalina.properties),这个文件默认存放在tomcat路径下的 bin/bootstrap.jar 中。锁定老帖子 主题:Tomcat 解析之初始化类加载器(截图)该帖已经被评为精华帖作者 正文 如图打开文件,其内容如下:Java代码 1. # Licensed to t
5、he Apache Software Foundation (ASF)under one or more 2. # contributor license agreements. See the NOTICE file distributed with 3. # this work for additional information regarding copyright ownership. 4. # The ASF licenses this file to You under the Apache License, Version 2.0 5. # (the “License“); y
6、ou may not use this file except in compliance with 6. # the License. You may obtain a copy of the License at 7. # 锁定老帖子 主题:Tomcat 解析之初始化类加载器(截图)该帖已经被评为精华帖作者 正文 8. # http:/www.apache.org/licenses/LICENSE-2.0 9. # 10.# Unless required by applicable law or agreed to in writing, software 11.# distribute
7、d under the License is distributed on an “AS IS“ BASIS, 12.# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13.# See the License for the specific language governing permissions and 14.# limitations under the License. 15. 16.# 17.# List of comma-separated packages that start
8、 with or equal this string 18.# will cause a security exception to be thrown when 19.# passed to checkPackageAccess unless the 20.# corresponding RuntimePermission (“accessClassInPackage.“+package) has 21.# been granted. 22.package.access=sun.,org.apache.catalina.,org.apache.coyote.,org.apache.tomca
9、t.,org.apache.jasper.,sun.beans. 23.# 24.# List of comma-separated packages that start with or equal this string 25.# will cause a security exception to be thrown when 26.# passed to checkPackageDefinition unless the 27.# corresponding RuntimePermission (“defineClassInPackage.“+package) has 28.# bee
10、n granted. 29.# 30.# by default, no packages are restricted for definition, and none of 31.# the class loaders supplied with the JDK call checkPackageDefinition. 锁定老帖子 主题:Tomcat 解析之初始化类加载器(截图)该帖已经被评为精华帖作者 正文 32.# 33.package.definition=sun.,java.,org.apache.catalina.,org.apache.coyote.,org.apache.tom
11、cat.,org.apache.jasper. 34. 35.# 36.# 37.# List of comma-separated paths defining the contents of the “common“ 38.# classloader. Prefixes should be used to define what is the repository type. 39.# Path may be relative to the CATALINA_HOME or CATALINA_BASE path or absolute. 40.# If left as blank,the
12、JVM system loader will be used as Catalinas “common“ 41.# loader. 42.# Examples: 43.# “foo“: Add this folder as a class repository 44.# “foo/*.jar“: Add all the JARs of the specified folder as class 45.# repositories 46.# “foo/bar.jar“: Add bar.jar as a class repository mon.loader=$catalina.home/lib
13、,$catalina.home/lib/*.jar 48. 49.# 50.# List of comma-separated paths defining the contents of the “server“ 51.# classloader. Prefixes should be used to define what is the repository type. 52.# Path may be relative to the CATALINA_HOME or CATALINA_BASE path or absolute. 53.# If left as blank, the “c
14、ommon“ loader will be used as Catalinas “server“ 54.# loader. 55.# Examples: 56.# “foo“: Add this folder as a class repository 锁定老帖子 主题:Tomcat 解析之初始化类加载器(截图)该帖已经被评为精华帖作者 正文 57.# “foo/*.jar“: Add all the JARs of the specified folder as class 58.# repositories 59.# “foo/bar.jar“: Add bar.jar as a clas
15、s repository 60.server.loader= 61. 62.# 63.# List of comma-separated paths defining the contents of the “shared“ 64.# classloader. Prefixes should be used to define what is the repository type. 65.# Path may be relative to the CATALINA_BASE path or absolute. If left as blank, 66.# the “common“ loade
16、r will be used as Catalinas “shared“ loader. 67.# Examples: 68.# “foo“: Add this folder as a class repository 69.# “foo/*.jar“: Add all the JARs of the specified folder as class 70.# repositories 71.# “foo/bar.jar“: Add bar.jar as a class repository 72.# Please note that for single jars, e.g. bar.ja
17、r, you need the URL form 73.# starting with file:. 74.shared.loader= 75. 76.# 77.# String cache configuration. 78.tomcat.util.buf.StringCache.byte.enabled=true 79.#tomcat.util.buf.StringCache.char.enabled=true 80.#tomcat.util.buf.StringCache.trainThreshold=50000081.#tomcat.util.buf.StringCache.cache
18、Size=5000 锁定老帖子 主题:Tomcat 解析之初始化类加载器(截图)该帖已经被评为精华帖作者 正文 此文件,下面会有详细的介绍.OK,到此,我们初步了解到 tomcat关于类加载器的一些知识。 下面来详细看看,tomcat 内部是怎么来初始化这些类加载器的吧.首先, 我们知道, java 程序都需要一个入口(main 方法), 而在 tomcat中,这个入口在 org.apache.catalina.startup.Bootstrap 这个类中。看其结构:锁定老帖子 主题:Tomcat 解析之初始化类加载器(截图)该帖已经被评为精华帖作者 正文 定位到方法内部: Java代码 1.
19、 public static void main(String args) 2. 3. if (daemon = null) 4. daemon = new Bootstrap(); 5. try 6. /初始化资源 (今天来了解的.) 7. daemon.init(); 锁定老帖子 主题:Tomcat 解析之初始化类加载器(截图)该帖已经被评为精华帖作者 正文 8. catch (Throwable t) 9. t.printStackTrace(); 10. return; 11. 12. 13. 14. try 15. /默认为启动 16. String command = “start
20、“; 17. if (args.length 0) 18. command = argsargs.length - 1; 19. 20. 21. if (command.equals(“startd“) 22. argsargs.length - 1 = “start“; 23. daemon.load(args); 24. daemon.start(); 25. else if (command.equals(“stopd“) 26. argsargs.length - 1 = “stop“; 27. daemon.stop(); 28. else if (command.equals(“s
21、tart“) 29. /设置标识 30. daemon.setAwait(true); 31. daemon.load(args); 32. /开启 33. daemon.start(); 34. else if (command.equals(“stop“) 35. daemon.stopServer(args); 36. else 37. log.warn(“Bootstrap: command “ +command + “ does not exist.“); 38. 39. catch (Throwable t) 40. t.printStackTrace(); 41. 锁定老帖子 主
22、题:Tomcat 解析之初始化类加载器(截图)该帖已经被评为精华帖作者 正文 42. 在 tomcat启动之前, 需要初始化一些系统资源, 初始化的详细工作都定义在 init()方法内部了。OK,我们继续追踪一下。 定位到 init()方法中.Java代码 1. public void init() 2. throws Exception 3. 4. / Set Catalina path 设置 catalina基本路径 5. setCatalinaHome(); 6. setCatalinaBase(); 7. 8. /初始化类加载器 9. initClassLoaders(); 10. 1
23、1. Thread.currentThread().setContextClassLoader(catalinaLoader); 12. SecurityClassLoad.securityClassLoad(catalinaLoader); 13. / Load our startup class and call its process() method 14. if (log.isDebugEnabled() 15. log.debug(“Loading startup class“); 16. Class startupClass = catalinaLoader.loadClass(
24、“org.apache.catalina.startup.Catalina“); 17. Object startupInstance = startupClass.newInstance(); 18. / Set the shared extensions class loader 19. if (log.isDebugEnabled() 20. log.debug(“Setting startup class propertie锁定老帖子 主题:Tomcat 解析之初始化类加载器(截图)该帖已经被评为精华帖作者 正文 s“); 21. String methodName = “setPar
25、entClassLoader“; 22. Class paramTypes = new Class1; 23. paramTypes0 = Class.forName(“java.lang.ClassLoader“); 24. Object paramValues = new Object1; 25. paramValues0 = sharedLoader; 26. Method method =startupInstance.getClass().getMethod(methodName, paramTypes); 27. method.invoke(startupInstance, par
26、amValues); 28. catalinaDaemon = startupInstance; 29. 可以看到, 上面的代码中,用来初始化类加载器、验证类加载器、以及使用类加载器来加载类“org.apache.catalina.startup.Catalina“等等操作。这篇文章,主要来探讨一下,tomcat 初始化类加载器的方式, ,所以,我们追踪到方法 initClassLoaders()中: 这里主要介绍一下,下面的流程, tomcat 会调用initClassLoaders()方法。用来初始化 common ,catalina,shared三种类加载器,而这个操作是通过方法crea
27、teClassLoader(String name, ClassLoader parent)来完成的。 而后 2个都属于 common的子级, 所以下面给出 2个方法的源代码(其中相关信息,都以注释给出): 锁定老帖子 主题:Tomcat 解析之初始化类加载器(截图)该帖已经被评为精华帖作者 正文 Java代码 1. /* 2. * 初始化类加载器: 3. * 加载三种: 4. * common. 5. * / 6. * catalina shared. 7. */ 8. private void initClassLoaders() 9. try 10. /创建 common类加载器 11.
28、 commonLoader = createClassLoader(“common“, null); 12. if( commonLoader = null ) 13. / no config file, default to this loader - we might be in a single env. 14. commonLoader=this.getClass().getClassLoader(); 15. 16. /创建 catalina类加载器,指定其父级别的加载器为 commonLoader. 17. catalinaLoader = createClassLoader(“s
29、erver“, commonLoader); 18. /创建 sharedLoader类加载器,指定其父级别的加载器为 commonLoader. 19. sharedLoader = createClassLoader(“shared“, commonLoader); 20. catch (Throwable t) 21. log.error(“Class loader creation threw exception“, t); 22. System.exit(1); 23. 24. 锁定老帖子 主题:Tomcat 解析之初始化类加载器(截图)该帖已经被评为精华帖作者 正文 Java代码
30、1. /* 2. * 创建类加载器 3. * 4. * param name 5. * param parent 指定上一级别的类加载器 6. * return 7. * throws Exception 8. */ 9. private ClassLoader createClassLoader(String name, ClassLoader parent) 10. throws Exception 11. /这里以 common为例: 从 catalina.properties中获取 common.loader 类加载信息 12. /如: 13. /common.loader=$cata
31、lina.home/lib,$catalina.home/lib/*.jar 14. String value = CatalinaProperties.getProperty(name + “.loader“); 15. / 如果没有任何信息,则返回父加载器 16. if (value = null) | (value.equals(“) 17. return parent; 18. 19. ArrayList repositoryLocations = new ArrayList(); 20. ArrayList repositoryTypes = new ArrayList(); 21.
32、 int i; 22. /以逗号分隔. 23. StringTokenizer tokenizer = new StringTokenizer(value, “,“); 24. 25. while (tokenizer.hasMoreElements() 26. String repository = tokenizer.nextToken(); 27. / Local repository 28. boolean replace = false; 锁定老帖子 主题:Tomcat 解析之初始化类加载器(截图)该帖已经被评为精华帖作者 正文 29. String before = reposit
33、ory; 30. /是否含有“$catalina.home“ 31. while (i=repository.indexOf(CATALINA_HOME_TOKEN)=0) 32. replace=true; 33. if (i0) 34. /替换成 tomcat路径 替换后的形式如下: c:/opensource/tomcat5/lib. 35. repository = repository.substring(0,i) + getCatalinaHome() 36. + repository.substring(i+CATALINA_HOME_TOKEN.length(); 37. el
34、se 38. repository = getCatalinaHome()39. + repository.substring(CATALINA_HOME_TOKEN.length(); 40. 41. 42. /是否含有“$catalina.base“ 43. while (i=repository.indexOf(CATALINA_BASE_TOKEN)=0) 44. replace=true; 45. if (i0) 46. /同上,替换 47. repository = repository.substring(0,i) + getCatalinaBase() 48. + reposi
35、tory.substring(i+CATALINA_BASE_TOKEN.length(); 49. else 50. repository = getCatalinaBase()51. + repository.substring(CATALINA_BASE_TOKEN.length(); 52. 53. 54. if (replace 56. 锁定老帖子 主题:Tomcat 解析之初始化类加载器(截图)该帖已经被评为精华帖作者 正文 57. / Check for a JAR URL repository 58. try 59. URL url=new URL(repository); 6
36、0. repositoryLocations.add(repository); 61. repositoryTypes.add(ClassLoaderFactory.IS_URL); 62. continue; 63. catch (MalformedURLException e) 64. / Ignore 65. 66. 67. 68. if (repository.endsWith(“*.jar“) 69. repository = repository.substring 70. (0, repository.length() -“*.jar“.length(); 71. reposit
37、oryLocations.add(repository); 72. repositoryTypes.add(ClassLoaderFactory.IS_GLOB); 73. else if (repository.endsWith(“.jar“) 74. repositoryLocations.add(repository); 75. repositoryTypes.add(ClassLoaderFactory.IS_JAR); 76. else 77. repositoryLocations.add(repository); 78. repositoryTypes.add(ClassLoad
38、erFactory.IS_DIR); 79. 80. 81. 82. 83. 84. String locations = (String) repositoryLocations.toArray(new String0); 85. Integer types = (Integer) repositoryTy锁定老帖子 主题:Tomcat 解析之初始化类加载器(截图)该帖已经被评为精华帖作者 正文 pes.toArray(new Integer0); 86. 87. /创建类加载器 88. ClassLoader classLoader = ClassLoaderFactory.createC
39、lassLoader 89. (locations, types, parent); 90. 91. / Retrieving MBean server 92. MBeanServer mBeanServer = null; 93. if (MBeanServerFactory.findMBeanServer(null).size() 0) 94. mBeanServer = 95. (MBeanServer) MBeanServerFactory.findMBeanServer(null).get(0); 96. else 97. mBeanServer = ManagementFactor
40、y.getPlatformMBeanServer(); 98. 99. 100. / Register the server classloader 101. ObjectName objectName = 102. new ObjectName(“Catalina:type=ServerClassLoader,name=“ + name); 103. mBeanServer.registerMBean(classLoader,objectName); 104. return classLoader; 105. 到这里,我们可以确定,tomcat 文档中的类加载器之间关系是准确的,并非凭空说的
41、。 到这里,我们可能对于 createClassLoader()方法的 Java代码 1. CatalinaProperties.getProperty(name + “.loader“); 锁定老帖子 主题:Tomcat 解析之初始化类加载器(截图)该帖已经被评为精华帖作者 正文 有点疑问, 到底 tomcat是如果通过配置文件来获取需要初始化类加载器的相关信息的呢/ 前面我们看到 catalina.properties 中记录了 tomcat三种类加载器中分别需要加载一些什么类的信息。 而 CatalinaProperties类正是用来解析此文件的,以告诉tomcat,哪种类加载器,加载哪
42、些类。我们来看看这个类的源代码: Java代码 1. /* 2. * Utility class to read the bootstrap Catalina configuration. 3. * 读取 tomcat 的配置文件 catalina.properties 4. * author Remy Maucherat 5. * version $Revision: 467222 $ $Date: 2006-10-24 11:17:11 +0800 (星期二, 24 十月 2006) $ 6. */ 7. 8. public class CatalinaProperties 9. / -
43、Static Variables 10. private static org.apache.juli.logging.Log log= 11. org.apache.juli.logging.LogFactory.getLog(CatalinaProperties.class ); 12. private static Properties properties = null; 13. 14. static 15. loadProperties(); 16. 17. 锁定老帖子 主题:Tomcat 解析之初始化类加载器(截图)该帖已经被评为精华帖作者 正文 18. 19. / - Publi
44、c Methods 20. 21. 22. /* 23. * Return specified property value. 24. */ 25. public static String getProperty(String name) 26. return properties.getProperty(name); 27. 28. 29. 30. /* 31. * Return specified property value. 32. */ 33. public static String getProperty(String name, String defaultValue) 34. return properties.getProperty(name, defaultValue); 35. 36. 37. 38. / - Public Methods 39. 40. 41. /* 42. * 加载配置信息 43. * Load