理解JVM虚拟机
1、真正理解编译器
2、分析类加载过程
加载:
加载class文件的信息加载到内存中。由硬盘到内存的迁移;
链接:
将加载阶段加载到内存中的二进制数据整合到虚拟机中。
验证:
文件格式验证、元数据验证等等
准备:
为类静态变量分配内存,并将其初始化为默认值,给常量分配内存并设置值
解析:
把类型中的符号引用转换为直接引用
初始化:为类的静态变量赋予正确的初始化值按照从上到下的顺序()
使用:这个阶段就是调用方法实例化出对象来使用了。
卸载:当类使用完了,在也用不到的时候就可以将类卸载了(必须保证所有的实例被GC(垃圾回收))
理解clinit和init
clinit: 类的静态变量初始化,类的静态语句块
init: 类变量初始化和类语句块、构造函数
在创建类的实例时,先调用clinit,再调用init
/*
1 为类的静态变量分配内存,并将其初始化为默认值,
singleTone = null Count1 = 0, Count2 = 0
2 为类的静态变量赋予正确的初始化值按照从上到下的顺序
singleTone = new SingleTone()
count1 = 1; count2 = 1;
正确的初始化
count2 = 0;
输出结果: count1 = 1; count2 = 0;
*/
class SingleTone {
private static SingleTone singleTone = new SingleTone();
public static int count1;
public static int count2 =0;
public SingleTone() {
count1 ++;
count2 ++;
}
public static SingleTone getInstance() {
return singleTone;
}
}
public class Main {
public static void main(String[] args) {
// write your code here
SingleTone instance = SingleTone.getInstance();
System.out.println("count1 = "+ instance.count1);
System.out.println("count2 = "+ instance.count2);
}
}
方法区:用于存储虚拟机加载的类信息、常量、静态变量、是各个线程共享的内存区域
程序计数器:它的作用是当前线程所执行的字节码的行号指示器
虚拟机栈:线程私有的,“栈帧”用于存储局部变量表(包括参数)、操作栈、方法出口等信息;
堆:被各个线程共享的内存、用来存放对象的