Java的虚拟机(JVM)的类加载子系统的解析过程

[

类加载子系统是JVM里面的一个重要的环节。与C/C++那些需要在编译器期进行连接工作的语言不同,Java类的加载、连接和初始化都是在程序运行时完成的,只有在类被需要的时候才进行动态加载。

1)JVM何时加载类?


有且只有以下5种情况:

  • 创建新对象(new)、设置/读取static字段(putstatic/getstatic)或调用静态方法(invokestatic)这四条指令时,如果该类没有初始化,则初始化。
  • 使用java.lang.reflect包得方法进行反射调用的时候,如果该类没有初始化,则初始化。
  • 当初始化一个类时,父类没有初始化,则先初始化父类。
  • 当虚拟机启动,需要执行main()的主类,JVM首先初始化该类。
  • JDK 1.7的动态语言支持时,如果java.lang.invoke.MethodHandle实例最后的解析结果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行过初始化,则初始化。

2)如何加载类?


类加载过程包括加载(Loading)、链接(Linking)和初始化(Initialization)三个过程。

Java的详解:JVM的类加载子系统的解析过程

加载(Loading)


  • 其中“根据全限定名获取字节流”的过程,可以有系统提供的类加载器完成,也可以由用户自定义类加载器。
  • 对于HotSpot,Class对象虽然是对象,但仍然存放在方法区中。

链接-准备


  • 该阶段值正式在方法区为类变量分配内存初始化类变量,
    public static int value = 123
    在准备阶段初始化零值,而非123。初始化123的过程在初始化阶段完成。

链接-解析


  • 将常量池中的符号引用替换成直接引用。其中对于非虚方法,在类加载阶段就可以确定调用的版本,因此可以在此阶段直接解析为直接引用;为对于虚方法(即支持多态),无法在此阶段确定调用版本,虚方法的符号引用需等到程序执行到该符号引用的字节码时才能解析为直接引用。
  • 解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法类型等符号引用。
  • 执行读写字段(getstatic、putstatic、getfield、putfield)、instanceof、方法调用(iinvokestatic、invokespecial、invokevirtual、invokedynamic)、new等操作符号引用的字节码之前,需要先进行符号引用解析。

初始化(Initialization)

  • 执行类构造器<clinit>:自动收集static变量和static{}块,按原文件出席西安的顺序执行初始化。
  • <clinit>由编译器自动生成,如果没有static变量和static{}块,就不会生成。

本文内容来自:Java的详解:JVM的类加载子系统的解析过程 – Break易站

]
转载请保留页面地址:https://www.breakyizhan.com/javamianshiti/2837.html
原文地址:https://www.cnblogs.com/breakyizhan/p/13295619.html