(1)概述
Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束而建立和销毁
(2)运行时数据区包含的内容
程序计数器
概述
当前线程所执行字节码的行号指示器
执行Java方法时表示字节码指令的地址
执行Native方法时,值为空
规定的异常
Java虚拟机中唯一没有规定OutOfMemoryError情况的区域
是否线程私有
线程私有
方法区
概述
方法区中的数据主要对应于“类加载”过程中“加载”阶段:“将这个字节流所代表的静态存储结构转化为“方法区”的运行时数据结构”这个步骤
可以处于物理上不连续的内存中,只要逻辑上连接即可,在实现时,既可实现成固定大小,也可以是扩展的
在程序中通过Class对象的getName、isInterface等方法获取的信息,从来源于该区域
该区域内存回收的目标主要是针对常量池回收和对类型卸载
内容
类信息
运行时常量池
存储内容
Class文件“常量池”中的信息,包括各种字面量和符号引用
类加载的“解析阶段”由符号引用翻译出来的的直接引用
特点
运行时常量池相对于Class文件常量池的不同是具备动态性,也就是运行期也可能将新的常量放入池中,用的多的是String类的inter()方法
静态变量
即时编译器编译后的代码
是否线程私有
所有线程共享
规定的异常
OutOfMemmoryError
如果堆中没有内存完成实例分配,并且堆也无法再扩展
运行时栈结构(虚拟机栈)
概述
每一个方法从调用开始至执行完成的过程,都对应着一个栈帧在虚拟机栈里面从入栈到出栈的过程
线程私有,生命周期与线程相同
在编译程序代码时,栈帧中需要多大局部变量表,多深的操作数栈都已经完全确定了,并且写入到方法表的Code属性之中,因此一个栈帧需要分配多少内存,不会受到程序运行期变量数据的影响,而仅仅取决于具体的虚拟机实现
栈桢内容
是否线程私有
规定的异常
本地方法栈
概述
与虚拟机栈的作用类似,区别在于为使用到的Native方法服务
虚拟机规范没有对本地方法栈的实现作强制规定,不同虚拟机可自由实现
Sun HotSpot直接把本地方法栈和虚拟机栈合二为一
规定的异常
StackOverflowError
线程请求的栈深度大于虚拟机所允许的深度
OutOfMemmoryError
如果虚拟机可以动态扩展,并且扩展时无法申请到足够的内存
堆
概述
存入对象实例,几乎所有的对象实例都在这里分配内存
Java虚拟机所管理内存中最大的一块,虚拟机启动时创建
Java堆可以处于物理上不连续的内存中,只要逻辑上连接即可
在实现时,既可实现成固定大小,也可以是扩展的,主流虚拟机都按可扩展来实现(通过-Xmx和-Xms控制)
堆内容
从内存回收角度看
新生代(Eden)
老年代(Old)
逃逸区
S0
S1
从内存分配角度看
线程共享的Java堆中可能划分出多个线程私有的分配缓存区
是否线程私有
所有线程共享
规定的异常
OutOfMemmoryError
如果堆中没有内存完成实例分配,并且堆也无法再扩展