JVM运行时数据区介绍[堆、栈、方法区、常量池]

时间:2022-12-27 11:12:55
程序计数器:当前线程所执行的字节码的行号指示器。


: 栈内存、虚拟机栈、或者说是虚拟机栈中的局部变量表。

用于存放编译期可知的各种 基本数据类型、对象引用类型[ 她可能是一个引用指针、也可能指向一个代表对象的句柄 ]

局部变量表所需的内存空间在编译器完成分配。


本地方法栈:为虚拟机找到的native方法服务


:虚拟机栈内存最大的一块,启动时候创建,所有线程共享的内存区域,此内存区域的唯一目的就是存放对象实例、

[虚拟机规范中描述:所有的对象实例以及数组都要分配在堆上],物理上不连续的内存空间,

        堆是gc管理的主要区域,采用分代收集算法,[年轻代、老年代、持久代] (分代是为了更好的回收内存|更快的分配内存)

通过-Xmx -Xms来配置  

年轻代 -> [Eden区  Survivor区(from、to 大小严格一致)]

新的对象首先放在Eden区,Survivor区作为Eden和Tenure(终生代)的缓冲,可以向Tenure转移活动的对象。

Tenure中存放生命周期长久的对象

Young和Tenure组成了堆内存


红色部分是容易混淆的,我们来看一个堆 OOM的监控截图


JVM运行时数据区介绍[堆、栈、方法区、常量池]

JVM运行时数据区介绍[堆、栈、方法区、常量池]



方法区:与堆一样,是一个线程共享的内存区域,他用于存储已经被虚拟机加载的类、常量、静态变量、即时编译器变异后的代码等。

虚拟机规范把方法区描述为堆的一个逻辑部分,但他有一个别名叫 NonHeap(非堆) 有人称为永久代(Permanent Generation)

垃圾收集行为在这个区域出现得比较少, 主要的回收目标是针对常量池的回收和对类型的卸载。

运行常量池:方法区的一部分,Class文件中还有一项常量池,用户存放编译期生存的各种字符量和符号引用,

这部分内容在类加载后存放到方法区的运行时常量池(PS 运行期间将新的常量放入池中用 String.intern())


直接内存:并不是虚拟机运行时数据区的一部分,但这部分内存被频繁的使用,也可能导致OOM。