JVM · Java虚拟机原理 · JVM上语言·框架· 生态系统编程语言爱好者Java 核心技术

类加载器

2021-05-03  本文已影响0人  蓝梅

一、类加载过程

当我们使用某个类时,JVM就会去加载我们需要使用的类

第一步:    找到类在磁盘上的位置,并加载进内存,主要是讲这部分(加载

第二步:校验字节码格式(校验

第三步:给静态变量赋初始值,例如 :int 默认为0;常量直接赋值(准备

第四步:将静态方法(例如 main方法 )替换为指向该静态方法的指针和内存句柄(直接引用),我们自己写的方法,将符号引用替换为直接引用(解析

第五步:对静态变量赋值,执行静态代码块(初始化

二、类加载器分类

    jvm默认的类加载器有:

    bootstrapLoader(加载java核心类库)

    extClassLoader(加载ext包)

    appClassLoader(加载classPath目录下的)

    个人理解,这些类加载器,主要是为了区分加载class的区域,实现保护java核心类

三、类加载器初始化过程

    在jvm虚拟机初始化时,会去初始化 sun.misc.Launcher 这个类

    我们来看看这个类初始化的源码

初始化Launcher类

它会去创建两个类,一个extClassLoader和一个appClassLoader,并且会把当前对象的loader属性赋值为appClassLoader,所以当类初始化时,默认是先从appClassLoader开始;

我们再来看看,初始化appClassLoader时,会传入extClassLoader,这一步做了什么呢?

getAppClassLoader方法实现 最后调用方法

我们一层一层往下找,当我们找到 ClassLoader 这个类时,就能看到,会把 parent 这个属性赋值为传入进来的classLoader类;所以这个地方我们就能看出,这个双亲委派机制的大概初始化。并且有一点得注意的是,这个是parent属性,并不是这个类的父类,想了解ClassLoader的继承关系,可以去看下源码,这里不详细讲解;

四、双亲委派机制

我们先看图,(插个题外话,最开始学习看源码时,总是喜欢了解一点点功能,就开始去看源码实现,结果发现,钻进去一头雾水;后来看源码时,就知道,一定是先去了解功能,了解他大概是怎么实现的,内部逻辑大概是什么,再去看源码,这样就能事半功倍)

双亲委派机制

从图可以看出来,先是看AppClassLoader是否有加载过,没有再向上委托,如果extClassLoader也没有加载过,则再向上委托,bootstrapLoader如果也没有加载过,则执行加载,加载不到,再extClassLoader加载,extClassLoader加载不到则AppClassLoader,最后,如果没有加载到,则抛出ClassNotFoundException;

我们来看看源码实现,主要是java.lang.ClassLoader#loadClass(java.lang.String, boolean)方法:

双亲委派机制源码

这个图就很清晰可以看出来,再就是要说明的是,为什么还有个findBootstrapClassOrNull这个方法,看上面Launcher 类的初始化方法,就能看出,extClassLoader是没有parent这个属性的,所以当找不到了,就使用bootstrapLoader类加载器

五、为什么要使用双亲委派机制

为什么要一层一层找,然后最后又绕回来?

个人理解:主要是为了核心类不被篡改,那为什么不从bootstrapLoader类加载器开始?觉得主要是因为我们自己的应用程序,常用的类,大部分都是我们自己写的,一经加载,再去获取的话,就只需要通过一层AppClassLoader,就能找到

如果我们想自己实现类加载,并且修改双亲委派机制的话,只需要实现ClassLoader,复写loadClass方法就可以了,值得注意的是,我们所有的的类的父类都是Object类,我们需要再复写时,考虑这个Object类的加载;

上一篇下一篇

猜你喜欢

热点阅读