028-JVM-类加载子系统面试题实战

204 阅读3分钟

从实践到理论总结的过程 。

package com.yuhl.c2020;

/**
 * @author yuhl
 * @Date 2020/12/27 13:55
 * @Classname Test2
 * @Description TODO
 */
public class Test2 {
    public static void main(String[] args) {
        System.out.println("最终的打印结果为:" + T.count);
        //System.out.println(T.finalCount);
    }
}
class T {
    public static int count = 2; //0
    public static T t = new T(); // null
    public final static int finalCount = 20; //0

    //private int m = 8;

    private T() {
        System.out.println("T类的无参数的构造方法被调用了!");
        System.out.println("count = " + count);
        count ++;
        System.out.println("我现在临时值:" + count);
        //System.out.println("--" + count);
    }
}

先给出答案:

T类的无参数的构造方法被调用了!
count = 2
我现在临时值:3
最终的打印结果为:3

2.1 System.out.println(“最终的打印结果为:” + T.count);

要打印 T.count 的值,需要下加载 T 仅内存,加载 class 文件进内存需要以下几步:

2.2 由 AppClassLoader 类加载器记载

2.3 verification 阶段判断 class 文件是否合法合规

2.4 preparation 为变脸服初值

此时:

public static int count = 0; //0
public static T t = null; // null

2.5 简介引用变直接引用:

是有有这步取决于此处的 boolean 值是否为真

2.6 initialization 阶段

  1. public static int count = 2; //0 赋值
  2. public static T t = new T(); 调用狗在其对 count ++; 所以 count=3
    分析完成。
package com.yuhl.c2020;

/**
 * @author yuhl
 * @Date 2020/12/27 13:55
 * @Classname Test2
 * @Description TODO
 */
public class Test2 {
    public static void main(String[] args) {
        System.out.println("最终的打印结果为:" + T.count);
        //System.out.println(T.finalCount);
    }
}
class T {
	public static T t = new T(); // null
    public static int count = 2; //0
    public final static int finalCount = 20; //0

    //private int m = 8;

    private T() {
        System.out.println("T类的无参数的构造方法被调用了!");
        System.out.println("count = " + count);
        count ++;
        System.out.println("我现在临时值:" + count);
        //System.out.println("--" + count);
    }
}

和上面例子的不同在于:

T类的无参数的构造方法被调用了!
count = 0
我现在临时值:1
最终的打印结果为:2

5.1 System.out.println(“最终的打印结果为:” + T.count);

要打印 T.count 的值,需要下加载 T 仅内存,加载 class 文件进内存需要以下几步:

5.2 由 AppClassLoader 类加载器记载

5.3 verification 阶段判断 class 文件是否合法合规

5.4 preparation 为变脸服初值

此时:

public static T t = null; // null
public static int count = 0; //0

5.5 简介引用变直接引用:

是有有这步取决于此处的 boolean 值是否为真

5.6 initialization 阶段

  1. public static T t = new T(); 调用狗在其对 count ++; 所以 count=1
    分析完成。
  2. 代码顺序执行 count = 2; 所以输出为 2.

要明白整个类加载子系统中各个阶段都做了什么事情。
通过这个例子应该很明白了整个过程了吧

  1. verification: 验证未见是否符合 jvm 规范,合法性检查
  2. preparation:静态变量默认值,记住是默认值哦!
  3. resolution:讲类、方法、属性的符号引用解析为直接引用,蝉联吃汇总的各种符号引用解析为指针,偏移量等内存地址的直接引用
  4. initializing: 嗲用类初始化代码 static 代码块、static 代码赋值(不是初值,是程序员福德之)哦!

自律的艰辛总甜过懊悔的苦果!
专注于 java 后端技术及解决方案,善于总结,分享!
自律的艰辛总甜过懊悔的苦果!
专注于 java 后端技术及解决方案,善于总结,分享!
自律的艰辛总甜过懊悔的苦果!
专注于 java 后端技术及解决方案,善于总结,分享!