JVM启动流程
JVM基本结构
PC寄存器
每个线程拥有一个PC寄存器
在线程创建时创建
指向下一条指令的地址
执行本地方法时,PC的值为undefined
方法区
保存装载的类信息
类型的常量池
字段,方法信息
方法字节码
通常和永久区(Perm)关联在一起
JDK6时,String等常量信息置于方法
JDK7时,已经移动到了堆
Java堆
和程序开发密切相关
应用系统对象都保存在Java堆中
所有线程共享Java堆
对分代GC来说,堆也是分代的
GC的主要工作区间
Java栈
线程私有
栈由一系列帧组成(因此Java栈也叫做帧栈)
帧保存一个方法的局部变量、操作数栈、常量池指针
每一次方法调用创建一个帧,并压栈
Java栈– 栈上分配
小对象(一般几十个bytes),在没有逃逸的情况下,可以直接分配在栈上
直接分配在栈上,可以自动回收,减轻GC压力
大对象或者逃逸对象无法栈上分配
栈、堆、方法区交互
内存模型
可见性
一个线程修改了变量,其他线程可以立即知道
保证可见性的方法
volatile
synchronized (unlock之前,写变量值回主存)
final(一旦初始化完成,其他线程就可见)
指令重排的基本原则
程序顺序原则:一个线程内保证语义的串行性
volatile规则:volatile变量的写,先发生于读
锁规则:解锁(unlock)必然发生在随后的加锁(lock)前
传递性:A先于B,B先于C 那么A必然先于C
线程的start方法先于它的每一个动作
线程的所有操作先于线程的终结(Thread.join())
线程的中断(interrupt())先于被中断线程的代码
对象的构造函数执行结束先于finalize()方法