JVM运行时内存划分
2022/5/28大约 3 分钟
一,JVM运行时内存划分

线程共享区:
- 方法堆
- java堆
线程独占区:
- 虚拟机栈
- 本地方法栈
- 程序计数区
1.1 虚拟机栈
- 虚拟机栈描述的是Java方法执行的动态内存模型;
- 栈帧:每一个方法的执行都会创建一个栈帧,伴随着方法从创建(压入虚拟机栈)到执行完成(弹出虚拟机栈)。用于存储局部变量表,操作数栈,动态链接,方法出口等。栈帧包含一个方法的主要信息。
- 局部变量表:存放编译期可知的各种基本数据类型,引用类型,方法的出口地址;局部变量表的内存空间,在编译期完成分配,当进入一个方法时,这个方法,需要在帧中分配的空间时固定的,在方法运行期间不会改变局部变量表的大小。
- StackOverFlowError:通常是递归调用方法不合理,导致虚拟机栈空间不够了
1.2 本地方法栈
在hotspot中,虚拟机栈和本地方法栈是同一块区域;

虚拟机栈和本地方法栈区别:
- 虚拟机栈是为虚拟机执行java方法服务的;
- 本地方法栈是为虚拟机执行native方法服务的;
1.3 程序计数区
- 程序计数器是一个比较小的内存空间,可以将其看作是当前线程锁执行的字节码的行号指示器。
- 程序计数器位于线程独占区
- 此区域是唯一没有OutOfMemroyError(内存溢出错误)错误的区域
1.4 堆
Java中堆内存划分:

在整个JVM的堆内存中实际上将内存分为了三部分:
新生代
新生代几乎是所有Java 对象出生的地方,即 Java 对象申请的内存以及存放都是在这个地方。Java 中的大部分对象通常不需长久存活,具有朝生夕死的性质,新生代是 GC 收集垃圾的频繁区域。新生代分为三个区:Eden 和 两个存活区(From 和 To),默认分别占内存的80%、10%、10% ,可以通过参数
–XX:SurvivorRatio来设定 。注: JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务,所以无论什么时候,总是有一块Survivor区域是空闲着的。因此,新生代实际可用的内存空间为 9/10 ( 即90% )的新生代空间。
老年代
存储被长时间使用的对象, 默认新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ,该值可以通过参数 –XX:NewRatio 来指定.
元空间(JDK1.8之前叫永久代)
存储一些方法中操作的临时对象等,JKD1.8之前是占用JVM内存,JDK1.8之后直接占用物理内存。取消永久代的目的是将 HotSpot和JRockit 的两个虚拟机标注联合为一个。
1.5 方法区
方法区主要存储已经被虚拟机加载的类信息、常量、静态变量、以及编译器编译后的代码等数据。