JVM 类加载机制 :加载,(验证,准备,解析),初始化

JVM 类加载的时机

1、使用new创建类的实例;访问某个类或接口的静态变量,或者对该静态变量赋值调用类的静态方法;即为(使用new、getstatic、putstatic、或invokestatic这4条指令时,这些命令对访问静态变量时会使得类加载,如果访问静态常量就不会因此加载类)。
2、使用反射包的方法对类发生调用时,反射(Class.forName(ClassName))
3、如果初始化一个类的时候,如果发现父类还没有初始化,则需要先触发其父类的初始化。
4、当虚拟机启动时,用户需要指定一个执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类。有且只有以上这四中情况才会触发初始化。

JVM 类不会加载的时机

1、通过子类类名调用父类静态代码,不会触发子类的初始化
2、通过数组来创建对象不会触发此类的初始化
3、通过调用静态常量(static final)不会触发初始化

类的加载步骤

加载,验证,准备,解析,初始化,卸载顺序固定,解析可以发生在初始化之前,为了支持动态绑定也可以发生在初始化阶段之后。

加载:类加载器,ClassLoader

步骤

(1)通过一个类的全限定名来获取其定义的二进制字节流,获取class二进制文件
(2)将这个字节流所代表的的静态存储结构转化为方法区的运行时数据结构
(3)在堆中生成一个代表这个类的Class对象,作为方法区中这些数据的访问入口。

验证

确保Class文件的字节流中包含的信息符合当前虚拟机的要求

准备:分配内存

准备阶段主要为类变量分配内存并设置初始值, 这些内存都在方法区分配。

加载静态变量

类的静态变量(static)在此分配内存并复制为类型的初始值(如int则为0),private static int a = 12; 中的a = 12 则被编译为putstatic,等待第一次初始化的时候执行。如果不仅是静态变量还加了final修饰 private static final int a = 12; ,那么分配内存与赋值将都在准备阶段中进行。

解析

这一阶段的任务就是把常量池中的符号引用转换为直接引用,jvm会将所有的类或接口名、字段名、方法名转换为具体的内存地址。

初始化(注意初始化不是生成对象实例,是执行静态变量赋值,执行静态代码块 )

<clinit>, https://www.jianshu.com/p/8a14ed0ed1e9

<clinit>在jvm第一次加载class文件时调用,因为是类级别的,所以只加载一次,是编译器自动收集类中所有类变量(static修饰的变量)和静态语句块(static{}),中的语句合并产生的,编译器收集的顺序,是由程序员在写在源文件中的代码的顺序决定的。 <init>实例构造器方法,在实例创建出来的时候调用,包括调用new操作符;调用Class或java.lang.reflect.Constructor对象的newInstance()方法;调用任何现有对象的clone()方法;通过java.io.ObjectInputStream类的getObject()方法反序列化。

版权声明:本文为CSDN博主「youngogo」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/youngogo/article/details/81866220

使用:创建对象,垃圾回收

卸载

类卸载即类的生命周期走到了最后一步,程序中不再有该类的引用,该类也就会被JVM执行垃圾回收,从此生命结束





除非注明,否则均为一叶呼呼原创文章,转载必须以链接形式标明本文链接

本文链接:http://www.yiyehu.tech/archives/2020/05/13/jvm-classloader

发表评论

电子邮件地址不会被公开。 必填项已用*标注