JVM的内存区域分为六部分,分别如下:
- 程序计数器
程序计数器是JVM内存区域中较小的一部分存放的是JVM字节码指令集,可以看成是当前线程执行的字节码行号指示器。比如在一个段代码中启动了两个线程。线程1首先执行,线程1执行到了第4行时退出,线程2要开始执行了。程序计数器就会记录下线程一当时执行到的地方,当线程一再次执行时就会从这里继续开始执行。
若当前执行的是java方法,程序计数器的值就是JVM字节码指令集
若是本地方法,程序计数器的值就是0
程序计数器是jvm六块内存区域里唯一一块不会产生OOM异常的区域。 - 虚拟机栈
虚拟机栈里存放的是java方法内存模型。
虚拟机栈生命周期与线程相同,在创建线程时,创建线程的虚拟机栈,线程执行结束完毕,虚拟机栈同线程一起被回收。
之前我们讲的栈区域实际上就是此处的虚拟机栈。
此区域一共会产生两种异常:
① 若线程请求的栈深度大于JVM允许的深度(-Xss设置栈容量),抛出StackOverFlowError异常。(常见于单线程)
②虚拟机在进行栈的动态扩展时,若无法申请到足够内存,抛出OOM(OutOfMemoryError)异常。
(常见于多线程) - 本地方法栈
存放本地方法(native方法)执行的内存模型。虚拟机栈是java方法内存模型。
HotSpot虚拟机中,本地方法栈与虚拟机栈是同一块内存区域。 - 堆(GC堆)
java堆(Java Heap)是JVM管理的最大内存区域。在JVM启动时创建。所有线程共享此内存,此内存中存放的都是对象实例以及数组。
Java堆是垃圾回收器管理的最主要内存区域。java堆可以处于物理上不连续的内存空间。
-Xmx设置堆最大值
-Xms设置堆最小值
若在堆中没有足够的内存完成对象实例分配并且堆无法再次扩展时。抛出OOM异常。
5.方法区
用于存储已被JVM加载的类信息、常量、静态变量等数据。JDK8以前,方法区也叫永久代,JDK8之后称为元空间(Meta Space)
方法区无法满足内存分配需求时,抛出OOM。
6.运行时常量池
运行时常量池其实是方法区的一部分,存放字面量与符号引用。
字面量:字符串常量(JDK7之后移到堆中)、final常量、基本数据类型的值。
符号引用:类、字段、方法的完全限定名、名称、描述符