一、Java虚拟机整体结构
二、JVM内存结构
(1)线程私有部分
1.本地方法栈:登记native方法,在执行引擎执行时加载本地方法库
2.程序计数器:就是一个指针,存储指向下一条指令的地址 ,由执行引擎读取下一条指令,
是一个非常小的空间,可以忽略不计 - 程序计数器的原因时CPU执行线程的时间分片导致的
3.java栈:Java线程执行方法的内存模型,一个线程对应一个栈,每个方法在执行的同时,
都会创建一个栈帧(用于存储局部变量表,操作数栈,动态链接,方法出口等信息),不存在
垃圾回收问题,只要线程一结束该栈就会释放,生命周期和线程一致
class Math{
public static final Integer CONSTANT_1 = 666;
public int math(){
int a = 1;
int b = 2;
int c = (a+b)*10;
return c;
}
public static void main(String[] args) {
Math math = new Math();
System.out.println(math.math());
System.out.println("end");
}
}
只要启动一个线程都会创建下面的结构,即程序计数器,Java栈,本地方法栈 都是线程私有的
因为栈数据结构的特点是先进后出,所以当Math.java启动后,
先创建main()-栈帧,放进Java栈,然后执行math()方法,再创建一个math()-栈帧放进Java栈,
当math()方法执行完成后,math()-栈帧后放进去,先被被弹出;
math()方法执行完成后,main方法才能执行完成,main()-栈帧先放进去,后被弹出
A:局部变量表 ----- >
int a = 1; int b = 2; ....
B:操作数栈 ----- > 执行 运算 (a + b) * 10 的数据过程
C:动态链接:在方法中new 一个对象,这个对象放入会放入堆中,这里会存在一个指针指向堆中的对象
D:方法出口
1)当线程请求的栈深度大于虚拟机栈所允许的深度,就会抛出StackOverFlowError异常
2)若虚拟机可动态扩展,当无法申请到足够的内存空间,就会抛出OutOfMemoryError异常
执行命令:1)javac Math.java把java文件变成class字节码文件
2)javap -c Math.class把字节码文件反汇编成指令文件
(2)线程共享部分
1.方法区:静态变量 + 常量 + 方法信息(构造方法/接口定义) + 运行时常量池 都存在方法区中,有一个别名叫
非堆(Non - Heap)
2.堆:虚拟机启动的时创建,用于存放对象实例,几乎所有对象(包含常量池)都在堆上分配内存,当对象无法在该空间申请到内存时,将抛出OutOfMemoryError异常;同时也是垃圾收集器管理的主要区域。可通过-Xmx -Xms参数来分别指定最大堆和最小堆
HotSpot是使用指针的方式来访问对象
reference存储的就直接是对象的地址
引申-java的四种变量的存储位置:
final修饰的变量----常量 JVM方法区
static修饰的变量----静态变量 JVM方法区