我试图理解Java堆术语中年轻的, 老和永久的代的概念,更具体地说,这三代之间的相互作用。
我的问题是:
Java虚拟机被组织成三代:年轻一代、老一代和永久一代。大多数对象最初是在年轻代中分配的。老代包含一些在年轻代集合中幸存下来的对象,以及一些可能直接在老代中分配的大型对象。永久生成保存JVM认为便于垃圾回收器管理的对象,例如描述类和方法的对象,以及类和方法本身。
这似乎是一个常见的误解。在Oracle的JVM中,永久生成不是堆的一部分。它是用于类定义和相关数据的单独空间。在Java 6和更早的版本中,被存储的字符串也存储在永久生成中。在Java 7中,被分隔的字符串存储在主对象堆中。
这里有一个关于永久的一代的好帖子。
我喜欢Oracle JConsole指南中每个空格的描述:
对于HotSpot Java虚拟机,内存 用于串行垃圾收集的池 Eden Space (heap):初始分配内存的池 对于大多数对象。 幸存者空间(heap):包含幸存对象的池 伊甸园的垃圾回收 李空间。< / > 永久生成(heap):包含已存在对象的池 . . 永久生成(非堆):包含所有反射的池 虚拟机本身的数据, 例如类和方法对象。与 使用类数据共享的Java虚拟机, 这一代人被分为 .只读和读写区 代码缓存(非堆):HotSpot Java虚拟机还包括一个代码缓存, 包含用于。的内存 编译和存储本机 李代码。< / >
对于HotSpot Java虚拟机,内存 用于串行垃圾收集的池
Java使用分代垃圾收集。这意味着如果你有一个对象foo(它是某个类的实例),它存活的垃圾收集事件越多(如果仍然有对它的引用),它就会被提升得越高。它开始于年轻一代(它本身被分为多个空间——伊甸园和幸存者),如果它存活足够长时间,最终将结束于老年一代。
堆分为年轻代和老代如下:
年轻的一代:这是一个居住时间很短的地方,分为两个空间:
老的代:这个池基本上包含终身的和虚拟的 (预留的)空间,并将保存那些幸存的对象
永久生成:这个内存池作为名称也说包含永久类元数据和描述符信息,所以永久生成空间总是为类和那些绑定到类(例如静态成员)保留。
Java8更新: PermGen替换为Metaspace,两者非常相似。 主要的区别是Metaspace可以动态地调整大小,也就是说,它可以在运行时扩展。 Java元空间空间:unbounded(默认)
代码缓存(虚拟或保留):如果你使用的是HotSpot Java VM,这包括包含内存的代码缓存区,将用于编译和存储本机代码。
礼貌
SunHotSpot JVM中的内存被组织成三代:年轻一代、老一代和永久一代。
供您参考:永久生成不被认为是Java堆的一部分。
三代人之间是怎样相互影响的? 对象(大型对象除外)首先分配给年轻代。如果一个对象在x之后仍然存活不。因此,我们可以说,年轻代包含寿命较短的对象,而老代包含寿命较长的对象。永久代不与其他两代交互
什么是年轻一代?
年轻的一代是所有新对象被分配和老化的地方。当年轻代填满时,这将导致一个小型垃圾收集。充满死对象的年轻代会很快被收集起来。一些幸存的对象会老化,并最终移动到老一代。
什么是老一代?
老的代用于存储长期存在的对象。通常,为年轻代对象设置一个阈值,当达到该年龄时,对象被移动到老代。最终需要收集老一代。这个事件被称为主要垃圾回收
什么是永久代?
永久的一代包含JVM所需的元数据,用于描述应用程序中使用的类和方法。JVM在运行时根据应用程序使用的类填充永久生成。
自Java 8发布以来,PermGen已被Metaspace取代。
PermSize,MaxPermSize参数现在将被忽略
这三代人之间是怎样相互影响的?
图片来源&oracle技术网络教程文章:http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
上面文章中的“一般垃圾收集过程”用很多图表解释了它们之间的相互作用。
请看总结图: