Java虚拟机内存结构——JDK1.8
一、Java虚拟机整体结构
二、JVM内存结构
(1)线程私有部分
1.本地方法栈:登记native方法,在执行引擎执行时加载本地方法库
2.程序计数器:就是一个指针,存储指向下一条指令的地址 ,由执行引擎读取下一条指令,
是一个非常小的空间,可以忽略不计
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:方法出口
注意:Java 针对Java栈区域规范了两种异常
1)当线程请求的栈深度大于虚拟机栈所允许的深度,就会抛出*Error异常
2)若虚拟机可动态扩展,当无法申请到足够的内存空间,就会抛出OutOfMemoryError异常
通过jvm参数 -Xss指定栈空间,空间大小决定栈调用深度
执行命令:1)javac Math.java把java文件变成class字节码文件
2)javap -c Math.class把字节码文件反汇编成指令文件
(2)线程共享部分
1.方法区:静态变量 + 常量 + 方法信息(构造方法/接口定义) + 运行时常量池 都存在方法区中,有一个别名叫
非堆(Non - Heap)
2.堆:虚拟机启动的时创建,用于存放对象实例,几乎所有对象(包含常量池)都在堆上分配内存,当对象无法在该空间申请到内存时,将抛出OutOfMemoryError异常;同时也是垃圾收集器管理的主要区域。可通过-Xmx -Xms参数来分别指定最大堆和最小堆
(3)Java栈+堆+方法区的交换关系
HotSpot是使用指针的方式来访问对象
Java堆中会存放访问类元数据的地址
reference存储的就直接是对象的地址