0
点赞
收藏
分享

微信扫一扫

一道面试题引出的Java加载、链接与初始化verification、preparation、resolution、initialization过程

背景试题

case 1

public class JavaLoading {

private static int NUM = 3;
private static JavaLoading INSTANCE = new JavaLoading();

private JavaLoading() {

NUM++;
}

public static void main(String[] args) {

System.out.println(INSTANCE.NUM);
}
}

case 2

public class JavaLoading {

private static JavaLoading INSTANCE = new JavaLoading();
private static int NUM = 3;

private JavaLoading() {

NUM++;
}

public static void main(String[] args) {

System.out.println(INSTANCE.NUM);
}
}

思考三秒钟……

case 1的输出是:4

case 2的输出是:3

根据java虚拟机规范,一个class被加载进内存后,需要进行链接(linking)与初始化(initialization)两步,

其中链接又分:验证(verification)、准备(preparation)、解析(resolution)三小步

一道面试题引出的Java加载、链接与初始化verification、preparation、resolution、initialization过程_开发语言

链接 linking

验证(verification)

确保class文件符合规范,能被虚拟机正确的识别

一道面试题引出的Java加载、链接与初始化verification、preparation、resolution、initialization过程_java虚拟机_02

准备(preparation)

Preparation involves creating the static fields for a class or interface and initializing such fields to their default values (§2.3, §2.4). This does not require the execution of any Java Virtual Machine code; explicit initializers for static fields are executed as part of initialization (§5.5), not preparation

准备阶段的工作包括为类和接口的静态成员变量赋默认值,这个阶段不会执行任何java虚拟机代码,静态变量的赋初始值是在初始化阶段,而不是在准备阶段(explicit initializers for static fields are executed as part of initialization , not preparation)

解析(resolution)

解析就是根据运行时常量池里的符号引用来动态决定具体值得过程。

一道面试题引出的Java加载、链接与初始化verification、preparation、resolution、initialization过程_开发语言_03

 

初始化 (initialization)

初始化就是执行初始化方法,静态变量的初始值在这个阶段完成赋值

一道面试题引出的Java加载、链接与初始化verification、preparation、resolution、initialization过程_java_04

 

类和接口初始化的条件

  1. 执行下列需要引用类或者接口的java虚拟机指令时,new/getstatic/putstatic或者invokestatic
  2. 在初次调用java.lang.invoke.MethodHandle实例时
  3. 在调用类库中的某些放射方法时,例如Class类中的java.lang.reflect包中的反射方法
  4. 在对类的某个子类进行初始化时
  5. 在它被选定为java虚拟机启动时的初始类时

一道面试题引出的Java加载、链接与初始化verification、preparation、resolution、initialization过程_开发语言_05

 一道面试题引出的Java加载、链接与初始化verification、preparation、resolution、initialization过程_后端_06

分析

回过头再去分析,case 1

public class JavaLoading {

private static int NUM = 3;
private static JavaLoading INSTANCE = new JavaLoading();

private JavaLoading() {

NUM++;
}


/**
* preparation 阶段 NUM = 0,INSTANCE = null
* initialization阶段 NUM = 3,INSTANCE = new JavaLoading(),在构造函数里 NUM++了
* 所以 NUM 最终值是 4
*/
public static void main(String[] args) {

System.out.println(INSTANCE.NUM);
}
}

分析,case 2

public class JavaLoading {

private static JavaLoading INSTANCE = new JavaLoading();
private static int NUM = 3;

private JavaLoading() {

NUM++;
}


/**
* preparation 阶段 INSTANCE = null, NUM = 0
* initialization阶段 INSTANCE = new JavaLoading(),在构造函数里 NUM++了,NUM变成了1,再执行 NUM = 3,
* 所以 NUM 最终值是 3
*/
public static void main(String[] args) {

System.out.println(INSTANCE.NUM);
}
}

你学废了吗?

一道面试题引出的Java加载、链接与初始化verification、preparation、resolution、initialization过程_初始化_07

 


举报

相关推荐

0 条评论