JVM之结构
JVM的运行流程
JVM的结构图如下:
类加载器
类加载器子系统负责加载编译好的.class字节码文件,并装入内存,使JVM可以实例化或以其它方式使用加载后的类。
程序计数器
记录当前线程执行到哪一行,每个线程有一个程序计数器和一个虚拟机栈;如果执行本地方法,程序计数器为空,这部分我们不需要深入研究。
虚拟机栈
虚拟机栈是线程私有的,每个线程创建的同时都会创建JVM栈,JVM栈中存放的为当前线程中局部基本类型的变量(java中定义的八种基本类型:boolean、char、byte、short、int、long、float、double)、部分的返回结果以及Stack Frame,非基本类型的对象在JVM栈上仅存放一个指向堆上的地址。
堆
它是JVM用来存储对象实例以及数组值的区域,可以认为Java中所有通过new创建的对象的内存都在此分配,因为对象都存在这里,所以也是线程共享的,Heap中的对象的内存需要等待GC进行回收。
方法区
用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译后的代码等信息。
方法区是线程间共享的,当两个线程同时需要加载一个类型时,只有一个类会请求ClassLoader加载,另一个线程会等待。
本地方法栈
JVM采用本地方法栈来支持native方法的执行,此区域用于存储每个native方法调用的状态。这部分也不需要我们深入学习。
了解JVM的运行流程
代码
public class Demo01 {
public static void main(String[] args) {
A a = new A();
System.out.println(a.width);
}
}
class A{
public static int width=100; //静态变量,静态域 field
static{
System.out.println("静态初始化类A");
width = 300 ;
}
public A() {
System.out.println("创建A类的对象");
}
}
分析
说明
这里主要根据虚拟机栈、堆、方法区,进行说明
1. JVM加载Demo01时候,首先在方法区中形成Demo01类对应静态数据(类变量、类方法、代码…),同时在堆里面也会形成java.lang.Class对象(反射对象),代表Demo01类,通过对象可以访问到类二进制结构。然后加载变量A类信息,同时也会在堆里面形成a对象,代表A类。
2. main方法执行时会在栈里面形成main方法栈帧,一个方法对应一个栈帧。如果main方法调用了别的方法,会在栈里面挨个往里压,main方法里面有个局部变量A类型的a,一开始a值为null,通过new调用类A的构造器,栈里面生成A()方法同时堆里面生成A对象,然后把A对象地址付给栈中的a,此时a拥有A对象地址。
3. 当调用A.width时,调用方法区数据。