1-tomcat-类加载器

发布于 2022年 02月 15日 05:04

                                            图1 tomcat类加载器

调试过程使用的都是默认参数,其他情况暂不考虑。

 java类加载器遵循双亲委派机制,原因:这样做可以维护一个优先级,保证java的核心类不会被覆盖。
但是tomcat在此基础上,又自定义了自己的类加载器。原因:

1. 启动tomcat本身需要--Application ClassLoader;
2. tomcat额外需要自己定制的依赖--Catalina ClassLoader(我的理解是可以对tomcat功能进行一些定制);
3. 为web应用加载一些公共资源--Shared ClassLoader;
4. 为 CatalinaClassLoader 和 Shared ClassLoader 加载公共资源-- Common ClassLoader;
5. web应用(也就是部署在wabapps目录下的应用)也需要一套依赖环境--WebAppClassLoader;

这里有几个点可能需要注意

1. 在默认参数下,虽然tomcat源码中调用了Thread.currentThread().setContextClassLoader(catalinaLoader);  但是tomcat本身的实际类加载器是Application ClassLoader(因为默认参数下,CatalinaClassLoader没有加载额外的资源,所以暂时不考虑);

可以通过一下代码验证:

图2 在web应用中调用Thread.currentThread().getContextClassLoader().getParent().getParent().loadClass("org.apache.catalina.startup.Catalina")由tomcat的类加载器机制可知: Thread.currentThread().getContextClassLoader().getParent().getParent() 得到的类加载器就是 Application ClassLoader

2. Springboot内置tomcat时使用的类加载机制,与部署在webapps目录下使用的类加载机制不同(以后在细说) 

3.ParallelWebappClassLoader虽然是自定义的类加载器,但还是符合Java的双亲委派机制的,或者说有选择性的双亲委派机制

              图3 ParallelWebappClassLoader继承了WebappClassLoaderBase

               图4 ParallelWebappClassLoader继承了WebappClassLoaderBase

为了验证第3点:

*在tomcat源码中Catalina.java中新增hi()方法;

*在编写的web应用中增加相同路径的Catalina.java

*在编写的web应用中反射调用Catalina.hi()方法,结果打印了tomcat源码中的方法调用结果

图5 验证

推荐文章