目录
- 1. 说明
- 2. 主要类加载器
- 2.1 Bootstrap类加载器
- 2.2 Common类加载器
- 2.3 Catalina类加载器
- 2.4 Shared类加载器
- 2.5 Web应用类加载器
- 2.5 JSP类加载器
- 3. 图示
- 4. 特点
- 5. 加载顺序
- 6. 面试题
1. 说明
- 1.tomcat的类加载机制是违反了双亲委派原则的,对于一些未加载的非基础类,各个web应用自己的类加载器(WebAppClassLoader)会优先查看自己的仓库加载,加载不到时再交给CommonClassLoader走双亲委派。
- 2.双亲委派模型要求除了顶层的启动类加载器之外,其余的类加载器都应当由自己的父类加载器加载。
- 3.tomcat为了实现隔离性,没有遵守双亲委派模型,每个WebAppClassLoader加载自己的目录下的class文件,不会传递给父类加载器。
2. 主要类加载器
2.1 Bootstrap类加载器
- 1.负责加载JVM启动所需的类,以及Tomcat自身的核心类,如Catalina和Coyote等。
- 2.这些类位于JVM的核心类库中,如%JAVA_HOME%/jre/lib目录。
2.2 Common类加载器
- 1.作为Tomcat的通用类加载器,负责加载Tomcat使用以及Web应用通用的一些类,这些类位于$CATALINA_HOME/lib目录下,如servlet-api.jar等。
- 2.Common类加载器是所有Web应用共享的,其加载的类对所有Web应用都可见。
2.3 Catalina类加载器
- 1.专门用于加载Tomcat内部使用的类,如Servlet容器、生命周期监听器等。
- 2.这些类对于Web应用是不可见的,以确保Tomcat内部组件的封装性和独立性。
- 3.Catalina类加载器以Common类加载器为父加载器。
2.4 Shared类加载器
- 1.负责加载Tomcat的共享库目录(如$CATALINA_HOME/shared/lib)下的类文件。
- 2.这些类对于所有的Web应用程序都是可见的,但与Common类加载器加载的类不同,Shared类加载器加载的类更侧重于Web应用之间的共享资源。
- 3.Shared类加载器同样以Common类加载器为父加载器。
2.5 Web应用类加载器
- 1.WebAppClassLoader。
- 2.每个Web应用程序都有一个独立的类加载器,即Web应用类加载器。
- 3.它负责加载Web应用程序目录下的类文件和库文件(位于/WEB-INF/classes和/WEB-INF/lib目录下)。
- 4.这些类加载器之间是相互隔离的,确保了不同Web应用程序之间的类隔离和资源隔离。
2.5 JSP类加载器
- 1.JasperLoader。
- 2.这个类加载器是Tomcat特有的,用于处理JSP文件的编译和加载过程。
- 3.JSP文件在Tomcat中实际上会被编译成Servlet类,然后再由Servlet容器来执行。这个编译和加载的过程就是由JSP类加载器来完成的。
- 4.每个JSP文件在Tomcat中都会对应一个唯一的JSP类加载器,这样做的主要目的是为了支持JSP文件的热部署和热替换功能。
- 5.当JSP文件被修改后,Tomcat能够检测到这种变化,并自动卸载旧的JSP类加载器,然后重新创建一个新的JSP类加载器来加载修改后的JSP文件。
- 6.用户就可以在不重启Tomcat服务器的情况下,看到JSP页面的更新内容,提高了开发和部署的效率。
3. 图示
4. 特点
- 1.类隔离:通过为每个Web应用程序分配独立的类加载器,Tomcat实现了不同Web应用程序之间的类隔离。这有助于避免类库冲突和依赖问题。
- 2.灵活性:由于Web应用类加载器是独立的,因此可以针对单个Web应用进行重新部署,而不会影响到其他Web应用。这提高了部署的灵活性和应用的可用性。
- 3.性能优化:由于每个Web应用都有自己的类加载器,Tomcat在加载类时不会搜索其他Web应用包含的Jar包,从而提高了类加载的性能。
- 4.违反双亲委派模型:Tomcat的类加载机制在一定程度上违反了Java的双亲委派模型。在某些情况下,Web应用类加载器会优先尝试加载类,而不是先委派给父类加载器。这是为了优先加载Web应用自己定义的类,以满足特定的需求。然而,这也带来了一定的风险,如类库冲突和安全问题。因此,在设计和使用Tomcat时,需要谨慎处理这些潜在的问题。
5. 加载顺序
- 1.使用bootstrap引导类加载器加载,加载JVM运行基本的类,以及标准扩展类(jre/lib/ext中的类)。
- 2.使用system系统类加载器加载,加载Catalina.bat中指定位置的类。
- 3.使用应用类加载器在WEB-INF/classes中加载。
- 4.使用应用类加载器在WEB-INF/lib中加载。
- 5.使用common类加载器在CATALINA_HOME/lib中加载,加载tomcat以及应用通用的类,位于CATALINA/lib下。
6. 面试题
- 1.tomcat不遵循双亲委派机制,如果自己定义一个恶意的HashMap,会不会有风险?
tomcat不遵循双亲委派机制,只是自定义的classloader顺序不同,但顶层还是相同的,
还是要去顶层请求classloader。
- 2.tomcat是个web容器,它解决了什么问题?
1.一个web容器可能需要部署两个应用程序,不同的应用程序可能会依赖同一个第三方类库的不同版本,不能要求同一个类库
在同一个服务器只有一份,因此要保证每个应用程序的类库都是独立的,保证相互隔离。
2.部署在同一个web容器中相同的类库相同的版本可以共享。
3.web容器也有自己依赖的类库,不能与应用程序的类库混淆。基于安全考虑,让容器的类库和程序的类库隔离开来。
4.web容器要支持jsp的修改,jsp文件最终也是要编译成class文件才能在虚拟机中运行,web容器需要支持jsp修改后不用
重启。
不行
1.如果使用默认的类加载器机制,无法加载两个相同类库的不同版本的,默认的类加载器是不管是什么版本,
只在乎全限定名类,并且只有一份。
2.无法实现jsp文件的热替换,jsp文件其实是class文件,如果修改,类名还是一样,类加载器会直接取方法
区中已经存在的,修改后的jsp是不会重新加载的。每个jsp文件对应一个唯一的类加载器,当一个jsp文件修
改了,就直接卸载这个jsp类加载器,重新创建类加载器,重新加载jsp文件。
- 4.tomcat的CommonClassLoader如何加载WebAppClassLoader中的类?
可以使用线程上下文类加载器实现,使用线程上下文加载器,可以让父类加载器请求子类加载器去完成类加载的动作。
- 5.为什么java文件放在Eclipse/IDEA中的src文件夹下会优先jar包中的class?
1.因为Eclipse/IDEA中src文件夹中的文件java以及webContent中的JSP都会在tomcat启动时,被编译成class文件放在
WEB-INF/class中。
2.Eclipse/IDEA外部引用的jar包,则相当于放在WEB-INF/lib中。
3.应用类加载器在WEB-INF/classes中加载优先于在WEB-INF/lib中加载。