============================================================================================================================================
========================================================================================================================================================
2.1、以Tomcat类加载为例,Tomcat 如果使用默认的双亲委派类加载机制行不行?
Tomcat需要解决什么问题?
- 一个web容器可能需要部署两个应用程序,不同的应用程序可能会依赖同一个第三方类库的不同版本,不能要求同一个类库在同一个
服务器只有一份,因此要保证每个应用程序的类库都是独立的,保证相互隔离。
-
部署在同一个web容器中相同的类库相同的版本可以共享。否则,如果服务器有10个应用程序,那么要有10份相同的类库加载进虚拟机。
-
web容器也有自己依赖的类库,不能与应用程序的类库混淆。基于安全考虑,应该让容器的类库和程序的类库隔离开来。
-
web容器要支持jsp的修改,我们知道,jsp 文件最终也是要编译成class文件才能在虚拟机中运行,但程序运行后修改jsp已经
是司空见惯的事情, web容器需要支持 jsp 修改后不用重启。
所以答案:Tomcat 如果使用默认的双亲委派类加载机制是不行的!!!
为什么不行?
1、第一个问题,如果使用默认的类加载器机制,那么是无法加载两个相同类库的不同版本的,默认的类加器是不管你是什么版本的,只在乎你的全限定类名,并且只有一份。
2、第二个问题,默认的类加载器是能够实现的,因为他的职责就是保证唯一性。
3、第三个问题和第一个问题一样。
4、第四个问题,我们想我们要怎么实现jsp文件的热加载,jsp 文件其实也就是class文件,那么如果修改了,但类名还是一样,
类加载器会直接取方法区中已经存在的,修改后的jsp是不会重新加载的。那么怎么办呢?我们可以直接卸载掉这jsp文件的类加载器,
所以你应该想到了,每个jsp文件对应一个唯一的类加载器,当一个jsp文件修改了,就直接卸载这个jsp类加载器。重新创建类加载器,重新加载jsp文件。
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
======================================================================================================================================================
tomcat的几个主要类加载器:
1、commonLoader:Tomcat最基本的类加载器,加载路径中的class可以被Tomcat容器本身以及各个Webapp访问;
2、catalinaLoader:Tomcat容器私有的类加载器,加载路径中的class对于Webapp不可见;
3、sharedLoader:各个Webapp共享的类加载器,加载路径中的class对于所有Webapp可见,但是对于Tomcat容器不可见;
4、WebappClassLoader:各个Webapp私有的类加载器,加载路径中的class只对当前Webapp可见,比如加载war包里相关的类,
每个war包应用都有自己的WebappClassLoader,实现相互隔离,比如不同war包应用引入了不同的spring版本,这样实现就能加载各自的spring版本;
从图中的委派关系中可以看出:
1、CommonClassLoader能加载的类都可以被CatalinaClassLoader和SharedClassLoader使用,
从而实现了公有类库的共用,而CatalinaClassLoader和SharedClassLoader自己能加载的类则与对方相互隔离。
2、WebAppClassLoader可以使用SharedClassLoader加载到的类,但各个WebAppClassLoader实例之间相互隔离。
3、而JasperLoader的加载范围仅仅是这个JSP文件所编译出来的那一个.Class文件,它出现的目的就是为了被丢弃:
当Web容器检测到JSP文件被修改时,会替换掉目前的JasperLoader的实例,并通过再建立一个新的Jsp类加载器来实现JSP文件的热加载功能。
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
由此可见,tomcat 这种类加载机制违背了java 推荐的双亲委派模型了吗?答案是:违背了。
很显然,tomcat 不是这样实现,tomcat 为了实现隔离性,没有遵守这个约定,每个webappClassLoader加载自己的目录下的class文件,不会传递给父类加载器,打破了双亲委派机制。
4、模拟实现Tomcat的webappClassLoader加载自己war包应用内不同版本类实现相互共存与隔离
=============================================================================================================================================================================================
public class MyClassLoaderTest {
static class MyClassLoader extends ClassLoader {
private String classPath;
public MyClassLoader(String classPath) {
this.classPath = classPath;
}
private byte[] loadByte(String name) throws Exception {
name = name.replaceAll(“\.”, “/”);
FileInputStream fis = new FileInputStream(classPath + “/” + name
- “.class”);
int len = fis.available();
byte[] data = new byte[len];
fis.read(data);
fis.close();
return data;
}
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
byte[] data = loadByte(name);
return defineClass(name, data, 0, data.length);
} catch (Exception e) {
e.printStackTrace();
throw new ClassNotFoundException();
}
}
/**
-
重写类加载方法,实现自己的加载逻辑,不委派给双亲加载
-
@param name
-
@param resolve
-
@return
-
@throws ClassNotFoundException
*/
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException {
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
笔者福利
以下是小编自己针对马上即将到来的金九银十准备的一套“面试宝典”,不管是技术还是HR的问题都有针对性的回答。
有了这个,面试踩雷?不存在的!
回馈粉丝,诚意满满!!!
aded
笔者福利
以下是小编自己针对马上即将到来的金九银十准备的一套“面试宝典”,不管是技术还是HR的问题都有针对性的回答。
有了这个,面试踩雷?不存在的!
回馈粉丝,诚意满满!!!
[外链图片转存中…(img-6uiCjJV0-1721182725180)]
[外链图片转存中…(img-NnD9h0VH-1721182725181)]
[外链图片转存中…(img-sx1J318O-1721182725181)]
[外链图片转存中…(img-B5obBErC-1721182725181)]