JVM的艺术—类加载器篇(二)

分享是价值的传递,喜欢就点个赞

引言

今天我们继续来深入的剖析类加载器的内容。上节课我们讲了类加载器的基本内容,没看过的小伙伴请加关注。今天我们继续。

什么是定义类加载器和初始化类加载器?

定义类加载器:假设我们的某一个类是由ExtClassLoader加载的,那么ExtClassLoader称为该类的定义类加载器

初始化加载器:能够返回Class对象引用的都叫做该类的初始类加载器,比如类A是由我们的ExtClassLoader加载,那么

ExtClassLoader是该类的定义类加载器,也是该类的初始类加载器,而我们的AppClassLoader也能返回我们A类的引用

那么AppClassLoader也是该类的初始类加载器。

什么是类加载器的双亲委派模型?

上篇文章我们提到了类加载器的双亲委派模型,也可以称为双亲委托模型。今天这篇文章我们就来把这个概念给讲明白。

概念:用一种简单的方式去描述双亲委托的概念。可以分为两个部分去理解

1委托:

jvm加载类的时候是通过双亲委派的方式去加载,自下而上的去委托。

自定义类加载器需要加载类时,先委托应用类加载器去加载,然后应用类加载器又向扩展类加载器去委托,扩展类加载器在向启动类加载器去委托。

如果启动类加载器不能加载该类。那么就向下加载

2加载:

jvm加载类的时候是通过双亲委派的方式去加载委托,但是加载的时候是由上向下去加载的,当委托到最顶层启动类加载器的时候,无法在向上委托,那么

启动类加载器就开始尝试去加载这个类,启动类加载器加载不了就向下交给扩展类加载器去加载,扩展类加载器加载不了就继续向下委托交给应用类加载器

去加载,以此类推。

如果文字描述你还不清楚什么是双亲委托机制,那么我画了一幅图可以更清楚类加载的过程。如下:

JVM的艺术—类加载器篇(二)

通过上图,我们知道更能清楚的知道,双亲委托模型的工作机制,用一句简单的话说,就是需要加载一个类的时候,向上委托,向下加载。

注意:在双亲委派机制中,各个加载器按照父子关系形成树型结构,除了根加载器以外,每一个加载器有且只有一个父加载器。

接下来,我也从jdk底层源码的角度给大家画了一张类加载的主要过程,图如下:

JVM的艺术—类加载器篇(二)

以上就是类加载器加载一个类的重要过程步骤。希望各位小伙儿可以结合源码的方式,仔细再研究一下。其实还挺好理解的。

下面咱们再说说,java采用双亲委托的方式去加载类,这样做的好处是什么呢?

双亲委派模型的好处

总所周知:java.lang.object类是所有类的父类,所以我们程序在运行期间会把java.lang.object类加载到内存中,假如java.lang.object类

能够被我们自定义类加载器去加载的话,那么jvm中就会存在多份Object的Class对象,而且这些Class对象是不兼容的。

所以双亲委派模型可以保证java核心类库下的类型的安全。

借助双亲委派模型,我们java核心类库的类必须是由我们的启动类加载器加载的,这样可以确保我们核心类库只会在jvm中存在一份

这就不会给自定义类加载器去加载我们核心类库的类。

根据我们的演示案例,一个class可以由多个类加载器去加载,同时可以在jvm内存中存在多个不同版本的Class对象,这些对象是不兼容的。

并且是不能相互转换的。

什么是全盘委托加载?

解释:假如我们的Person类是由我们的系统类APP类加载器加载的,而person类所依赖的Dog类也会委托给App系统类进 行加载,这个委托过程也遵循双亲委派模型。代码如下

person类代码中创建Dog实例

public class Person {

public Person(){ new Dog(); }

}

public class Dog { public Dog(){ System.out.println("Dog 的构造函数"); } }

测试类

public class MainClass02 { public static void main(String[] args) throws Exception { //创建自定义类加载器的一个实例,并且通过构造器指定名称 Test01ClassLoader myClassLoader = new Test01ClassLoader("loader1"); myClassLoader.setPath("I:\\test\\"); Class<?> classz = myClassLoader.loadClass("com.test.Person"); System.out.println(classz.getClassLoader()); System.out.println(Dog.class.getClassLoader()); } } 运行结果: sun.misc.Launcher$AppClassLoader@18b4aac2 sun.misc.Launcher$AppClassLoader@18b4aac2 Process finished with exit code 0

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgyxwp.html