java类加载机制

2020-05-23  本文已影响0人  乌木山

一、类加载概念

我们知道,在java中,我们的java代码在编译之后最终会以class文件的形式存在。jvm就是通过加载class文件来执行程序。

类加载的过程如下,首先jvm虚拟机读取class二进制文件,将数据读取到数据区的方法区内(todo jvm内存模型),然后在堆区创建一个java.lang.Class的对象(没错,类本质上也对应着一个对象),用来统一封装堆数据区的类结构,提供统一的访问方式和接口。

二、类加载流程

class文件在jvm的生命周期包含如下几个关键流程:


class文件生命周期

加载

加载主要做了以下几件事:

链接

  1. 验证

验证主要是对文件数据格式的正确性等进行校验操作。

  1. 准备

为类的静态成员变量分配内存空间及默认初始值,该初始值是类型的默认值,而非代码中显式指定的值。(显式指定的值在初始化阶段才会被处理)

  1. 解析

将类中的符号引用替换为直接引用。

初始化

  1. 初始化时机:使用该类的时候
    1.Class.forName的方式加载类实例。
    2.访问类的静态变量、方法,或者访问类的静态方法。
    3.初始化该类的子类(子类初始化时,会先触发父类初始化完毕)
    4.jvm表明为启动类的类
  2. 初始化步骤

三、类加载方式

java类加载有两种方式
ClassLoader.loadClass
这种方式只会执行加载和链接过程,不会对类进行初始化
Class.forName
这种方式在加载链接之后,还会对类执行初始化。当然也可以通过Class.forName(String name, boolean initialize, ClassLoader loader) 决定是否执行初始化环节。

四、双亲委派模型

jvm的加载器整体如下图,其中最重要的特性就是双亲委派。所谓的双亲委派其实就是,当底层的APPClassLoader需要加载一个类时,会首先向上层的ExtClassLoader询问是否已经加载相关类,而ExtClassLoader会进一步询问BootStrapLoader是否已加载所需类。通过这种方式,可以保证整个JVM里一个类只被加载一次。

类加载器 (1).png

五、常见问题

 ClassLoader.getSystemClassLoader().loadClass("notExistClass");

而如果jvm运行时,去实例化或者使用一个类时,发现类不存在,则会抛出Error。例如我们程序中引入一个Ajar包,而A中依赖B类,B类对应的Jar包我们没有引入,那么当我们使用A类时,jvm会尝试去加载B类,进而会抛出NoClassDefFoundError

参考文献

https://zhuanlan.zhihu.com/p/25228545
https://juejin.im/post/5cfdeea2e51d454d1d6284e7

上一篇 下一篇

猜你喜欢

热点阅读