深入JVM内核(一)JVM内存区域与运行机制
date: 2018-10-03 13:01:52
JVM启动流程
JVM基本结构
程序计数器
- 每个线程拥有一个PC寄存器
- 在线程创建时创建
- 指向下一条指令的地址
- 执行本地方法师,PC的值为undefined
方法区
- 所有线程共享
- 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
Java堆
- 所有线程共享
- 和程序开发密切相关
- 几乎所有的对象实例都在这里分配内存
- 对分代GC来说,堆也是分代的
- GC的主要工作区间
Java虚拟机栈
- 线程私有
- 生命周期与线程相同
- 栈由一系列帧组成(因此Java栈也叫做栈帧)
- 帧用于存储局部变量、操作数栈、动态链接、方法出口等信息
- 方法从调用到执行完成的过程,就对应一个栈帧在虚拟机栈中入栈到出栈的过程
- 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常
本地方法栈
- Java虚拟机栈发挥的作用相似
- 区别在于:
- 虚拟机栈为虚拟机执行Java方法(也就是字节码)服务
- 本地方法栈为虚拟机使用到的Native方法服务
堆、栈、方法区的交互
public class AppMain {
//运行时, jvm 把appmain的信息都放入方法区
public static void main(String[] args) {
//main 方法本身放入方法区。
Sample test1 = new Sample( " 测试1 " );
//test1是引用,所以放到栈区里, Sample是自定义对象应该放到堆里面
Sample test2 = new Sample( " 测试2 " );
test1.printName();
test2.printName();
}
public class Sample {
//运行时, jvm 把appmain的信息都放入方法区
private name;
//new Sample实例后, name 引用放入栈区里, name 对象放入堆里
public Sample(String name) {
this .name = name;
}
//print方法本身放入 方法区里。
public void printName() {
System.out.println(name);
}
}
JVM内存模型
内存模型
- 每一个线程有一个工作内存和主存独立
- 工作内存存放主存中变量的值的拷贝
- 当数据从主内存复制到工作存储时,必须出现两个动作:第一,由主内存执行的读(read)操作;第二,由工作内存执行的相应的load操作;当数据从工作内存拷贝到主内存时,也出现两个操作:第一个,由工作内存执行的存储(store)操作;第二,由主内存执行的相应的写(write)操作.
- 每一个操作都是原子的,即执行期间不会被中断
- 对于普通变量,一个线程中更新的值,不能马上反应在其他线程中
如果需要在其他线程中立即可见,需要使用 volatile 关键字
参考:
- 周志明. 深入理解JVM虚拟机