Java面试_类加载:双亲委派机制

Java 类加载:双亲委派机制

在讲“双亲委派机制”前,首先要讲一讲类和类加载器的关系。如果对类加载还不太熟悉的话,也可以直接到我之前转载的一篇关于类加载的文章,戳我。

类加载器:
我们定义下的类,如果我们要使用这个类,首先就是要把“.java”这个文件便以成class文件,然后由对应的“类加载器”加载到JVM中,我们才能使用这个类对象。
一般情况下,类的记载是在启动程序时有JVM来完成的,但是某些场景需要我们自己手动去指定加载某个类,这个时候就要用到Class.forName(String className)记载/找到这个className对应的类。

类记载器类型:

  1. Bootstrap Class Loader: 这是JDK自带的一款类加载器,用于加载JDK内部的类,用来加载$JAVA_HOME/jre/lib下面的那些类
  2. Extension Class Loader:这个主要是加载JDK扩展包里的类,一般是在$JAVA_HOME/lib/ext下面的包中的类
  3. Application Class Loader: 用于记载开发人员中自己平时写的应用代码的类的,加载存放在classpath路径下的哪些应用程序级别的类的
    Java面试_类加载:双亲委派机制_第1张图片

双亲委派机制?
在oracle的官方翁文档中,对于这个委派机制是这么描述的:

The Java platform uses a delegation model for loading classes. The basic idea is that every class loader has a “parent” class loader. When loading a class, a class loader first “delegates” the search for the class to its parent class loader before attempting to find the class itself.

翻译成中文意思是(我使用的是谷歌翻译):
Java平台使用委托模型来加载类。基本思想是每个类加载器都有一个“父”类加载器。在加载类时,类加载器首先将对类的搜索“委托”到其父类加载器,然后再尝试查找类本身。

下面两幅图为正确以及错误的理解:
错误理解:Java面试_类加载:双亲委派机制_第2张图片
正确理解:
Java面试_类加载:双亲委派机制_第3张图片
所以正确的名称应该为父委派模型

“父委派模型”是怎么工作的?
例如,我们写了一个测试类Test.class,我们需要加载java.lang.String,那么加载流程如下所示:都是向上委托父类加载器去完成的。
Java面试_类加载:双亲委派机制_第4张图片

父委派模型的好处
父委派机制的好处是保证了系统类别的类的安全性,是一些基础类不受开发人员定制化的破坏。,就例如Java.lang.String这个类基本上所有使用Java的都知道,那么如果没有父委派模型,而是由各个类加载器自行加载的话,那么如果我编写一个名称为java.lang.String的类的话,并放在程序中的Classpath中,那么系统中就会出现多个String类,那么到时候究竟要加载哪一个,应用程序也会变得一片混乱。

什么时候父委派模型是失效的?
1.通过预加载的方式
2.通过Thread.getContextClassLoader();

怎么打破双亲委派机制
自己写一个类加载器。继承CLoader类并重写loadclass方法和findclass方法

关于Tomcat的类加载机制:
Tomcat的类加载机制并不遵循父委派模型。下图是Tomcat类加载器的结构:、
Java面试_类加载:双亲委派机制_第5张图片
从图中的委派关系中可以看出:

1.CommonClassLoader能加载的类都可以被Catalina ClassLoader和SharedClassLoader使用,从而实现了公有类库的共用。
2.CatalinaClassLoader和Shared ClassLoader自己能加载的类则与对方相互隔离。
3.WebAppClassLoader可以使用SharedClassLoader加载到的类,但各个WebAppClassLoader实例之间相互隔离。
4.JasperLoader的加载范围仅仅是这个JSP文件所编译出来的那一个.Class文件,它出现的目的就是为了被丢弃:当Web容器检测到JSP文件被修改时,会替换掉目前的JasperLoader的实例,并通过再建立一个新的Jsp类加载器来实现JSP文件的HotSwap功能。

Tomcat违背了父委派模型
tomcat违背了父委派模型,因为双亲代理机制也就是父委派模型要求除了顶层启动类加载器之外,其余的类加载都应该由其父类加载器加载。而Tomcat不是这样实现的,Tomcat为了实现隔离性,没有遵循这个约定,每个WebappCLoader加载自己目录下的class文件,不会传递给父类加载器

你可能感兴趣的:(Java面试)