计算机系统应用教程网站

网站首页 > 技术文章 正文

「每天进步一点点」java类加载机制

btikc 2024-11-02 11:08:52 技术文章 4 ℃ 0 评论

当用java命令运行某个main函数时,首先需要类加载器把主类加载到JVM内存中。

下面就是一个class文件大致的加载流程:


如上图 将编译好的字节码class文件通过java命令,在win操作系统就是一个java.exe文件,这个文件底层是c++语言实现的,通过这个文件调用底层jvm.dll文件创建Java虚拟机,这个jvm.dll文件也是c++语言实现的就是一些类库。在创建JVM虚拟机的过程中会通过c++语言创建一个引导类加载器。最终由C++语言调用java代码创建JVM启动器Launcher,该类由引导类加载器创建其他类加载器,最终调用的Launcher类的getLauncher()方法,这个方法创建加载了扩展类加载器,应用程序类加载器。最终调用loadClass()方法实现类的加载。

其中loadClass的类加载过程有如下几步:

加载

在硬盘上查找并通过IO读入字节码文件,使用到类时才会加载,例如调用类的main()方法,new对象等等,在加载阶段会在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口

验证

校验字节码文件的正确性,不会危害虚拟机自身的安全

准备

给类的静态变量分配内存,并赋予默认值



解析

将符号引用替换为直接引用,该阶段会把一些静态方法(符号引用,比如 main()方法)替换为指向数据所存内存的指针或句柄等(直接引用),这是所谓的静态链接过 程(类加载期间完成),动态链接是在程序运行期间完成的将符号引用替换为直接引用

初始化

对于初始化阶段,虚拟机严格规范了有且只有5种情况下,必须对类进行初始化(只有主动去使用类才会初始化类):

  • 当遇到getstatic、putstatic或invokestatic 这4条直接码指令时,比如读取一个静态字段(未被 final 修饰)、或调用一个类的静态方法时。
  • 使用new关键字实例对象。
  • 使用 java.lang.reflect 包的方法对类进行反射调用时如Class.forName(""),newInstance()等等。如果类没初始化,需要触发其初始化。
  • 初始化一个类,如果其父类还未初始化,则先触发该父类的初始化。
  • 当虚拟机启动时,用户需要定义一个要执行的主类 (包含 main 方法的那个类),虚拟机会先初始化这个类。
  • 当一个接口中定义了JDK8新加入的默认方法(被default关键字修饰的接口方法)时,如果有这个接口的实现类发生了初始化,那该接口要在其之前被初始化。

卸载

卸载类需要满足3个要求:

  • 该类的所有的实例对象都已被GC,也就是说堆不存在该类的实例对象。
  • 该类没有在其他任何地方被引用
  • 该类的类加载器的实例已被GC

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表