我正在尝试理解Java堆术语中的年轻代、老年代和永久代的概念,特别是它们之间的相互作用。
我的问题如下:
- 什么是年轻代?
- 什么是老年代?
- 什么是永久代?
- 这三个代之间如何相互作用/关联?
我正在尝试理解Java堆术语中的年轻代、老年代和永久代的概念,特别是它们之间的相互作用。
我的问题如下:
这似乎是一个常见的误解。在Oracle的JVM中,永久代不是堆的一部分。它是一个单独的空间,用于存储类定义和相关数据。在Java 6及更早版本中,字符串池也存储在永久代中。在Java 7中,字符串池存储在主对象堆中。
这篇关于永久代的文章很好。
我喜欢Oracle的JConsole指南中给出的每个空间的描述:
对于HotSpot Java VM,使用串行垃圾回收的内存池如下:
- 伊甸园空间(堆):为大多数对象最初分配内存的池。
- 幸存者空间(堆):包含已经从伊甸园空间垃圾回收过来的对象。
- 老年代(堆):包含已经在幸存者空间中存在一段时间的对象。
- 永久代(非堆):包含虚拟机本身的所有反射数据,例如类和方法对象。对于使用类数据共享的Java VM,此代被分为只读区域和可读写区域。
- 代码缓存(非堆):HotSpot Java VM还包括一个代码缓存,其中包含用于编译和存储本机代码的内存。
Java使用分代垃圾回收。这意味着如果您有一个名为foo的对象(它是某个类的实例),它经过更多的垃圾回收事件(如果仍然有对它的引用),就会被推广得越多。它从年轻代开始(年轻代本身又分为多个空间-伊甸园和幸存者),最终可能在老年代中存活。
堆(Hep)可分为年轻代和老年代,具体如下:
年轻代:这是对象生命周期短暂的地方,又分为两个空间:
老年代: 这个池主要包含永久代和虚拟(保留)空间,将存放在年轻代垃圾回收后仍存活的对象。
永久代: 内存池中包含永久类元数据和描述符信息,因此永久代空间总是为类和与之相关的内容预留,例如静态成员。
Java8更新:永久代已被元空间(Metaspace)所代替,非常相似。
主要区别在于Metaspace可以在运行时动态调整大小。
Java Metaspace空间:无界(默认)
代码缓存(Code Cache): (虚拟或保留) : 如果使用HotSpot Java VM,则包括包含内存的代码缓存区,在其中进行编译和本地代码存储。
什么是年轻代?
年轻代用于分配和回收新的对象。当年轻代被填满时,会触发一次小型垃圾收集。年轻代中死亡的对象会很快被回收。一些存活的对象会被移动到老年代。
什么是老年代?
老年代用于存储生命周期较长的对象。通常设置一个阈值来判断对象是否应该从年轻代移动到老年代。最终老年代也需要进行垃圾回收,这个事件被称为大型垃圾回收。
什么是永久代?
永久代包含JVM运行所需的元数据信息,描述应用程序中使用的类和方法。永久代在运行时根据应用程序使用的类进行填充。
自Java 8发布以来,PermGen已被Metaspace取代。
现在将忽略PermSize和MaxPermSize参数。
这三代如何相互交互/关联?
图片来源和Oracle Technetwork教程文章: http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
以上文章中的"垃圾回收过程概述"通过多个图示详细解释了三代之间的交互关系。
请参考下面的总结图:
该段内容是一个HTML代码块,其中包含了一个超链接和图像标签。需要注意的是,需要保留原有的HTML标签以确保页面正常渲染。