加载阶段
链接阶段
初始化阶段
初始化
初始化阶段就是执行类构造器方法
的过程
此方法不需要定义,是javac编译器自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并起来
构造方法中指令按语句在源文件中出现的顺序执行
不同于类的构造器(构造器是虚拟机视角下的
)
若该类有父类,JVM会保证子类的
执行前,父类的
已经执行完毕
虚拟机必须保证一个类的
方法在多线程情况下被同步加锁
public class ClassClinitTest {
private static int num = 1;
static {
num = 2;
number = 20;
System.out.println(num);
// System.out.println(number); 报错 非法的前向引用
}
private static int number = 10; //linking的prepare: number = 0 --> initial: 20 --> 10
public static void main(String[] args) {
System.out.println(ClassClinitTest.num);//2
System.out.println(ClassClinitTest.number);//10
}
}
的指令
0 iconst_1
1 putstatic #3
4 iconst_2
5 putstatic #3
8 bipush 20
10 putstatic #5
13 getstatic #2
16 getstatic #3
19 invokevirtual #4
22 bipush 10
24 putstatic #5
27 return
注意:
如果没有静态变量就不会有
方法
方法是构造器函数(任何一个类声明后,至少会存在一个构造器)
不同于类的构造器(构造器是虚拟机视角下的
)
package com.ambitfly.java;
public class InitTest {
// 任何一个类声明后,至少会存在一个构造器
private int a = 1;
private static int c = 3;
public static void main(String[] args) {
int b = 2;
}
}
方法指令
0 aload_0
1 invokespecial #1 >
4 aload_0
5 iconst_1
6 putfield #2
9 return
自定义构造器
package com.ambitfly.java;
public class InitTest {
// 任何一个类声明后,至少会存在一个构造器
private int a = 1;
private static int c = 3;
public InitTest(){
a = 4;
}
public static void main(String[] args) {
int b = 2;
}
}
方法指令
0 aload_0
1 invokespecial #1 >
4 aload_0
5 iconst_1
6 putfield #2
9 aload_0
10 iconst_4
11 putfield #2
14 return
若该类有父类,JVM会保证子类的
执行前,父类的
已经执行完毕
public class ClinitTest {
static class Father {
public static int A = 1;
static {
A = 2;
}
static class Son extends Father{
public static int B = A;
}
public static void main(String[] args) {
System.out.println(Son.B);//2
}
}
}
指令
0 getstatic #2
3 putstatic #3
6 return
虚拟机必须保证一个类的
方法在多线程情况下被同步加锁
package com.ambitfly.java;
public class DeadThreadTest {
public static void main(String[] args) {
Runnable r = () -> {
System.out.println(Thread.currentThread().getName() + "开始");
DeadThread dead = new DeadThread();
System.out.println(Thread.currentThread().getName() + "结束");
};
Thread t1 = new Thread(r, "线程1");
Thread t2 = new Thread(r, "线程2");
t1.start();
t2.start();
}
}
class DeadThread {
static {
if(true){
System.out.println(Thread.currentThread().getName() + "初始化当前类");
while (true){
}
}
}
}
/**
运行结果:
线程1开始
线程2开始
线程2初始化当前类
*/