jvm内存区域
运行时数据区域
程序计数器
- 程序计数器是属于线程私有的
- 记录了当前线程切换前程序所处于的位置,方便线程切换回来后,能恢复的正确的执行位置
- 如果运行的是Java方法,则记录的是虚拟机字节码指令的地址,如果是本地方法,这个计数器为空
Java虚拟机栈
- java虚拟机栈也是线程私有的
- 在每个方法运行时都会创建一个栈帧,记录局部变量表,操作数栈,动态链接等信息
- 当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,方法运行期间是不会改变局部变量表的
局部变量表
- 存放了编译器可知的基本数据类型,对象引用,returnAddress类型
本地方法栈
- 与虚拟机栈相似,只不过为本地方法服务
Java堆
- Java堆是线程公有的
- 此内存区域的唯一目的就是存放对象实例,几乎所有的实例都在堆中分配。
- 有一部分内存实在栈上分配的(通过逃逸分析)
- java堆是垃圾回收管理的主要区域
逃逸分析
- 方法逃逸
当一个对象在方法中定义之后,作为参数传递到其它方法中
- 线程逃逸
如类变量或实例变量,可能被其它线程访问到
优化
如果不存在逃逸行为,则可以对该对象进行如下优化
- 同步消除
线程同步本身比较耗时,如果逃逸分析确定不会掏出线程,则消除同步,开启同步消除需要先开启逃逸分析典型例子stringBuffer.append("");
- 标量替换
- 标量是指不可分割的量,如java中基本数据类型和reference类型,相对的一个数据可以继续分解,称为聚合量
- 如果把一个对象拆散,将其成员变量恢复到基本类型来访问就叫做标量替换
- 如果逃逸分析发现一个对象不会被外部访问,并且该对象可以被拆散,那么经过优化之后,并不直接生成该对象,而是在栈上创建若干个成员变量
- 栈上分配
在栈上分配对象
方法区
- 是线程共享区域
- 通常加载类信息,常量,静态变量,即时编译后的代码等
- 这里需要知道永久代与方法区不对等,只是Hotspot使用永久代来实现方法区,其他虚拟机并不是
运行时常量池
- 是方法区的一部分
- 常量池(用于存放编译器生产的各种字面量和符号引用)