整理自《深入理解java虚拟机》
① Java虚拟机运行时数据区
方法区、堆、虚拟机栈、本地方法栈、程序计数器
a. 程序计数器
可以看作是当前线程所执行的字节码的行号指示器,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。
每个线程都需要一个独立的程序计数器——线程私有。
此内存区域是唯一一个在java虚拟机规范中没有规定任何OutMemoryError情况的区域。
b. Java虚拟机栈
线程私有——生命周期与线程相同
每个方法在执行时会创建一个栈帧,用于存储局部变量,操作数栈,动态链接,方法出口等信息,每一个方法从调用到执行完成的过程就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
如果线程请求的深度大于虚拟机所允许的深度,将抛出stackOverflowError异常,虽然大部分java虚拟机都可动态扩展,但是如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常
c. 本地方法栈
线程私有
本地方法栈与虚拟机栈所发挥的作用是相似的,但是虚拟机栈为虚拟机执行java方法,本地方法栈则为虚拟机使用到的native方法服务。HotSpot虚拟机将这两个栈合二为一,本地方法栈也会抛出StackOverflowError和OutOfMemoryError异常
d. 堆
所有线程共享——存放对象实例
垃圾收集器管理的主要区域
由于现在收集器基本都采用分代收集算法,所以还可以细分为新生代和老年代,
再细致一点的有Eden空间、From Survivor空间、To Survivor空间等。如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。
e. 方法区
线程共享
存储已被虚拟机加载的类信息、常量、静态变量,即时编译器编译后的代码等数据。
当方法区无法满足内存分配需求时,将抛出OutOfMemoryError
运行时常量池——方法区的一部分,用于存放编译期生成的各种字面量和符号引用。当常量池无法再申请到内存时会抛出OutOfMemoryError异常
-Xmx10240m -Xms10240m -Xmn5120m -XXSurvivorRatio=3
-Xmx:最大堆大小
-Xms:初始堆大小
-Xmn:年轻代大小
-XXSurvivorRatio:年轻代中Eden区与Survivor区的大小比值
年轻代5120m, Eden:Survivor=3,Survivor区大小=1024m(Survivor区有两个,即将年轻代分为5份,每个Survivor区占一份),总大小为2048m。
-Xms初始堆大小即最小内存值为10240m