JVM类加载过程实例

JVM类加载过程实例

package com.lbl;


public class ClassInitTest {
    
    
    private static int num=1;

    static {
    
    
        num=2;
        number=20;
    }

    private static int number=10;
    public static void main(String[] args) {
    
    
        System.out.println(ClassInitTest.num);
        System.out.println(ClassInitTest.number);
    }
}

输出结果:

2

10

jclasslib图:
jclasslib图

由这图,可以看出,先是把number赋值了20,然后再赋值为了10,也就是说,是按顺序,先执行了number=20,然后才执行了private static int number=10

那么问题就来了,明明number变量的声明在后面,为什么number可以直接赋值20呢?

因为类的加载分三个阶段:Loading、Linking、initialization

Linking:

其中的第二个阶段Linking阶段(链接)又分三个:验证(verify)、准备(prepare)、解析(Resolve)

其中的准备(prepare)阶段描述:

为类变量分配内存并且设置该类变量的默认初始值,即零值。

这里不包含用final修饰的static,因为final在编译的时候就会分配了,准备阶段会显式初始化

这里不会为实例变量分配初始化,类变量会分配的方法区中,而实例变量会随着对象一起分配到java堆中。

initiallization:

  • 初始化阶段就是执行类构造器方法()的过程

  • 此方法不需要定义,是java编译器自动收集类中的所有变量的赋值动作和静态代码中的语句合并而来。

  • 构造器方法中指令按语句在源文件中出现的顺序执行

  • ()不同于类的构造器。(关联:构造器是虚拟机视角下的())

  • 若该类具有父类,jvm会保证子类的()执行前,父类()已经执行完毕

  • 虚拟机必须保证一个类的()方法在多线程下被同步加锁

看明白上面的知识后,最终就可以得出结论:

结论

猜你喜欢

转载自blog.csdn.net/qq_37924905/article/details/108476006