- 浏览: 1012693 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (826)
- 硬件 (8)
- 软件 (24)
- 软件工程 (34)
- JAVA (229)
- C/C++/C# (77)
- JavaScript (8)
- PHP (1)
- Ruby (3)
- MySQL (14)
- 数据库 (19)
- 心情记事 (12)
- 团队管理 (19)
- Hadoop (1)
- spring (22)
- mybatis(ibatis) (7)
- tomcat (16)
- velocity (0)
- 系统架构 (6)
- JMX (8)
- proxool (1)
- 开发工具 (16)
- python (10)
- JVM (27)
- servlet (5)
- JMS (26)
- ant (2)
- 设计模式 (5)
- 智力题 (2)
- 面试题收集 (1)
- 孙子兵法 (16)
- 测试 (1)
- 数据结构 (7)
- 算法 (22)
- Android (11)
- 汽车驾驶 (1)
- lucene (1)
- memcache (12)
- 技术架构 (7)
- OTP-Erlang (7)
- memcached (17)
- redis (20)
- 浏览器插件 (3)
- sqlite (3)
- Heritrix (9)
- Java线程 (1)
- scala (0)
- Mina (6)
- 汇编 (2)
- Netty (15)
- libevent (0)
- CentOS (12)
- mongod (5)
- mac os (0)
最新评论
-
kingasdfg:
你这里面存在一个错误添加多个任务 应该是这样的 /** * ...
Quartz的任务的临时启动和暂停和恢复【转】 -
kyzeng:
纠正一个错误,long型对应的符号是J,不是L。
Jni中C++和Java的参数传递 -
zhaohaolin:
抱歉,兄弟,只是留下作记录,方便学习,如果觉得资料不好,可以到 ...
netty的个人使用心得【转】 -
cccoooccooco:
谢谢!自己一直以为虚机得使用网线才可以与主机连接呢。。
主机网卡无网线连接与虚拟机通信 -
yuqilin001:
要转别人的东西,请转清楚点嘛,少了这么多类,误人子弟
netty的个人使用心得【转】
tomcat 7 源码分析-2 类加载ClassLoader
tomcat在启动的时候使用了三个类加载器
- 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 );
- }
- }
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
- common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar
- server.loader=
- 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的位置,做了一些字符串的处理。
- 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);
- }
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()中加载
Class<?> startupClass = catalinaLoader.loadClass ("org.apache.catalina.startup.Catalina");
这个才是tomcat的守护进程。
- 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;
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()直到类第一次使用的时候才 初始化。
发表评论
-
tomcat7.0.8的高级应用-apr1.4.2安装
2011-03-24 17:16 985一 windows下安装 直接 ... -
tomcat 7 源码分析-14 tomcat的container设计
2011-03-11 19:18 1546tomcat 7 源码分析-14 tomca ... -
tomcat 7 源码分析-13 处理request的Valve和Valve的链表Pipeline
2011-03-11 19:17 1129tomcat 7 源码分析-13 处理request的Val ... -
tomcat 7 源码分析-12 Enumeration枚举
2011-03-11 19:14 1252tomcat 7 源码分析-12 Enumeration枚举 ... -
tomcat 7 源码分析-11 tomcat对http协议的实现
2011-03-11 19:13 1402tomcat 7 源码分析-11 tomcat对http协议 ... -
tomcat 7 源码分析-10 线程池ThreadPoolExecutor
2011-03-11 19:12 2212tomcat 7 源码分析-10 线程池ThreadPool ... -
tomcat 7 源码分析-9 tomcat对ServerSocket的封装和使用
2011-03-11 19:11 1637tomcat 7 源码分析-9 tomcat对ServerS ... -
tomcat 7 源码分析-8 生命周期lifecycle和监听listener
2011-03-11 19:10 1386tomcat 7 源码分析-8 生命周期lifecycle和 ... -
tomcat 7 源码分析-7 server初始化中的JMX(DynamicMBean)再续
2011-03-11 19:09 1042tomcat 7 源码分析-7 server初始化中的JMX ... -
tomcat 7 源码分析-6 server初始化中的JMX(DynamicMBean)续
2011-03-11 19:08 1189tomcat 7 源码分析-6 server ... -
tomcat 7 源码分析-5 server初始化中的JMX(DynamicMBean)
2011-03-11 19:08 1365tomcat 7 源码分析-5 server初始化中的JMX ... -
tomcat 7 源码分析-4 server初始化背后getServer().init()
2011-03-11 19:06 1352tomcat 7 源码分析-4 server初始化背后get ... -
tomcat 7 源码分析-3 使用Digester读取xml文件实例化server
2011-03-11 19:05 1388tomcat 7 源码分析-3 使用Digester读取xm ... -
tomcat 7 源码分析-1 关于读取properties及注册系统properties
2011-03-11 19:02 1592tomcat 7 源码分析-1 关于读取properties ... -
Tomcat的四种基于HTTP协议的Connector性能比较
2011-03-11 17:58 1114Tomcat的四种基于HTTP协议的Connector性能比较 ...
相关推荐
Apache Tomcat 7.0.81 源码分析 Apache Tomcat 是一个流行的开源软件,用Java语言编写,是实现Java Servlet和JavaServer Pages(JSP)规范的应用服务器,广泛用于Web应用的开发和部署。源码的下载对于开发者来说...
4. **类加载器**:Tomcat使用自定义的类加载器来加载Web应用的类,这使得不同应用之间的类可以隔离,避免冲突。源码中,ClassLoader的实现(例如`org.apache.catalina.loader.WebappClassLoaderBase`)值得深入研究...
2. Webapp ClassLoader:每个Web应用程序都有自己的Webapp ClassLoader,用于加载WEB-INF/classes和WEB-INF/lib下的类,遵循"父子优先"原则,优先尝试从父类加载器加载,如果找不到再从自身加载。 3. Shared ...
Tomcat7源码还涉及到了类加载机制,它采用了自定义的类加载器,如`CatalinaClassLoader`和`SharedClassLoader`,理解这些类加载器的工作方式有助于解决类冲突和加载顺序问题。 此外,Tomcat的安全管理也是重要一环...
通过对Tomcat 5.0.18 ClassLoader的源码分析,我们可以更好地理解和控制应用的类加载行为,这对于解决类冲突、优化性能和提高安全性都至关重要。在实际开发中,理解这些细节可以帮助我们更高效地部署和调试Java Web...
5. **ClassLoader机制**:Tomcat的类加载机制允许每个Web应用拥有自己的类加载器,避免类冲突。理解这部分源码对于理解和解决部署问题至关重要。 6. **Session管理**:Tomcat处理用户会话,包括创建、跟踪和管理...
5. **ClassLoader机制**:Tomcat使用自定义的ClassLoader来加载Web应用程序的类,确保不同应用之间的类隔离,防止冲突。 Tomcat 6.0.18版的特性包括: 1. **性能优化**:相对于之前的版本,6.0.18进行了性能调优,...
在这个项目中,开发者可能已经配置了相关的Maven插件和目标,以便于编译、测试和打包Tomcat源码。 【标签】: 1. **Tomcat8**:Tomcat 8是Tomcat服务器的第8个主要版本,它支持Java Servlet 3.1、JavaServer Pages...
通过阅读"TOMCAT源码分析.doc"和解压后的"apache-tomcat-6.0.0-src.zip",你可以深入了解上述知识点,并学习如何根据源码进行调试、优化或扩展Tomcat。这份资料对于Java Web开发者来说是一份宝贵的参考资料,有助于...
Tomcat使用自定义的ClassLoader来加载Web应用的类,这使得每个应用可以有自己的类空间,避免类冲突。Classloading策略是理解和调试Tomcat应用的重要部分。 7. **Session管理** Tomcat提供了会话管理机制,包括...
3. **启动流程**:Tomcat的启动过程始于`bin/catalina.sh`或`catalina.bat`,这些脚本会初始化Java环境,并加载`catalina.jar`中的`org.apache.catalina.startup.ClassLoader`,接着加载`Server`对象,初始化`...
5. **ClassLoader**:Tomcat使用自定义的ClassLoader来加载Web应用的类。这使得不同应用之间能隔离地运行,避免类冲突。 6. **Lifecycle**:所有Tomcat组件都遵循生命周期接口,如`org.apache.catalina.Lifecycle`...
了解并研究Tomcat源码对于深入理解Web服务器的工作原理,优化应用程序性能,以及解决可能出现的技术问题都具有重要意义。 1. **Servlet与JSP**: - **Servlet**:Servlet是Java编程语言中的一个接口,它定义了Web...
本篇文章将深入探讨Tomcat如何打破双亲委派模型,并通过源码分析和图表解析来帮助理解这一机制。 首先,我们需要了解Java的双亲委派模型。这个模型是由JDK中的ClassLoader实现的,默认情况下,当一个类加载器需要...