首页 > 代码库 > 细说tomcat之类加载器
细说tomcat之类加载器
官网:http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html
Java类加载与Tomcat类加载器层级关系对比
Java ClassLoader: Bootstrap ClassLoader(加载$JAVA_HOME/jre/lib/目录下核心类库:resources.jar,rt.jar,sunrsasign.jar,jsse.jar,jce.jar,charsets.jar,jfr.jar,以及jre/classes目录下的class) /| | Tomcat ClassLoader: ExtClassLoader(加载$JAVA_HOME/jre/lib/ext/目下的所有jar) -------- Bootstrap(加载$JAVA_HOME/jre/lib/ext/目录下的所有jar) /|\ /| | | AppClassLoader(加载应用程序classpath目录下的所有jar和class文件) System(加载$CATALINA_HOME/bin/bootstrap.jar,$CATALINA_BASE/bin/tomcat-juli.jar,$CATALINA_HOME/bin/commons-daemon.jar) /| | Common(加载$CATALINA_BASE/lib和$CATALINA_HOME/lib下的class,资源和jar文件) /| | WebAppClassLoader(加载WebApp/WEB-INF/classes,WebApp/WEB-INF/lib)
Java ClassLoader验证:
public class ClassLoaderTest { public static void main(String[] args) { ClassLoader appClassLoader = ClassLoaderTest.class.getClassLoader(); ClassLoader extClassLoader = appClassLoader.getParent(); ClassLoader bootstrapClassLoader = extClassLoader.getParent(); System.out.println(appClassLoader); System.out.println(extClassLoader); System.out.println(bootstrapClassLoader); } }
输出:
sun.misc.Launcher$AppClassLoader@73d16e93
sun.misc.Launcher$ExtClassLoader@15db9742
nul
Tomcat ClassLoader验证:
public class ClassLoaderServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ClassLoader loader = this.getClass().getClassLoader(); while(loader != null) { System.out.println(loader); loader = loader.getParent(); } System.out.println(loader); } }
输出:
ParallelWebappClassLoader
context: test-web
delegate: false
----------> Parent Classloader:
java.net.URLClassLoader@379619aa
java.net.URLClassLoader@379619aa
sun.misc.Launcher$AppClassLoader@764c12b6
sun.misc.Launcher$ExtClassLoader@1a93a7ca
null
跟踪org.apache.catalina.loader.ParallelWebappClassLoader源码发现,org.apache.catalina.loader.WebappClassLoaderBase重写了toString()方法:
@Override public String toString() { StringBuilder sb = new StringBuilder(this.getClass().getSimpleName()); sb.append("\r\n context: "); sb.append(getContextName()); sb.append("\r\n delegate: "); sb.append(delegate); sb.append("\r\n"); if (this.parent != null) { sb.append("----------> Parent Classloader:\r\n"); sb.append(this.parent.toString()); sb.append("\r\n"); } if (this.transformers.size() > 0) { sb.append("----------> Class file transformers:\r\n"); for (ClassFileTransformer transformer : this.transformers) { sb.append(transformer).append("\r\n"); } } return (sb.toString()); }
也就是说,Tomcat的ClassLoader结构为:
null(JVM Bootstrap ClassLoader)
sun.misc.Launcher$ExtClassLoader@1a93a7ca
sun.misc.Launcher$AppClassLoader@764c12b6
java.net.URLClassLoader@379619aa
org.apache.catalina.loader.ParallelWebappClassLoader
Tomcat Common ClassLoader默认的搜索顺序为:
(1)unpacked classes and resources in $CATALINA_BASE/lib
(2)JAR files in $CATALINA_BASE/lib
(3)unpacked classes and resources in $CATALINA_BASE/lib
(4)JAR files in $CATALINA_HOME/lib
tomcat classloader类图
总结:
1. Java装载类使用“全盘负责委托机制”。
“全盘负责”是指当一个ClassLoder装载一个类时,除非显示地使用另外一个ClassLoder,否则该类所依赖及引用的类也由这个ClassLoder载入;
“委托机制”是指先委托父类装载器寻找目标类,只有在找不到的情况下才从自己的类路径中查找并装载目标类。
2. Tomcat的WebAppClassLoade默认不使用“委托机制”,查找class和资源的顺序如下:
(1)Bootstrap classes of your JVM (2)/WEB-INF/classes of your web application (3)/WEB-INF/lib/*.jar of your web application (4)System class loader classes (5)Common class loader classes If the web application class loader is configured with <Loader delegate="true"/> then the order becomes: (1)Bootstrap classes of your JVM (2)System class loader classes (3)Common class loader classes (4)/WEB-INF/classes of your web application (5)/WEB-INF/lib/*.jar of your web application
3. Tomcat中变量$CATALINA_BASE和$CATALINA_HOME的含义
Throughout the docs, you‘ll notice there are numerous references to $CATALINA_HOME的含义. This represents the root of your Tomcat installation. When we say, "This information can be found in your $CATALINA_HOME/README.txt file" we mean to look at the README.txt file at the root of your Tomcat install. Optionally, Tomcat may be configured for multiple instances by defining $CATALINA_BASE for each instance. If multiple instances are not configured, $CATALINA_BASE is the same as $CATALINA_HOME.
一言以蔽之;如果没有明确设置CATALINA_BASE变量,则CATALINA_BASE与CATALINA_BASE值相同,都是值tomcat安装目录。
【参考】
http://www.hollischuang.com/archives/199 深度分析Java的ClassLoader机制(源码级别)
http://blog.csdn.net/xyang81/article/details/7292380 深入分析Java ClassLoader原理
细说tomcat之类加载器