我对 Heap、Young、Tenured 和 Perm 一代感到困惑。
谁能解释一下?
Java 垃圾收集器称为分代垃圾收集器。应用程序中的对象存在不同的时间长度,具体取决于它们的创建位置和使用方式。这里的关键见解是,对短期和长期对象使用不同的垃圾收集策略允许针对每种情况专门优化 GC。
粗略地说,当对象在年轻代中“存活”重复的垃圾回收时,它们会迁移到永久代。永久代是一种特殊情况,它包含 JVM 所需的对象,这些对象不一定在您的程序中表示,例如表示类和方法的对象。
由于年轻代通常会包含大量垃圾,因此它针对一次摆脱大量未使用对象进行了优化。 Tenured Generation 因为它包含更长寿命的对象,所以针对快速垃圾收集进行了优化,而不会浪费大量内存。
随着垃圾收集技术的改进,细节变得相当复杂,并且取决于您的 JVM 及其配置方式。如果您需要确切了解正在发生的事情,您应该阅读您正在使用的特定 JVM 的 documentation。
也就是说,有一个简单的历史安排,这在概念层面上仍然有用。从历史上看,年轻一代是copy collector,老年一代是mark and sweep collector。 复制收集器基本上不需要 CPU 成本来清除垃圾,大部分成本是维护活动对象,这种效率的代价是更重的内存使用。 标记和清除收集器为活动和未使用的对象支付了一些 CPU 成本,但更有效地利用了内存。
Java 堆内存 是操作系统分配给 JVM 的内存的一部分。每当我们创建对象时,它们都会在 heap in java 中创建。
为了垃圾回收,Java 堆空间被划分为三个区域或代,称为年轻代、老年代或终身代和永久代。永久代是在热点 JVM 中的完整 gc 期间收集的垃圾
年轻代是所有新对象被分配和老化的地方。当年轻代填满时,这会导致次要垃圾收集。一个充满死亡对象的年轻代很快就会被收集起来。一些幸存的对象被老化并最终移动到老年代。
老一代用于存储长期存活的对象。通常,为年轻代对象设置一个阈值,当满足该年龄时,该对象将移动到老年代。最终需要收集老年代。此事件称为重大垃圾回收。
永久代包含 JVM 所需的元数据,用于描述应用程序中使用的类和方法。 JVM 在运行时根据应用程序使用的类填充永久代。
PermGen 自 Java 8 发布以来已被 Metaspace 取代。 PermSize & MaxPermSize 参数现在将被忽略。看看 Pierre - Hugues Charbonneau 的这篇dzone article,了解 Metaspace。
https://i.stack.imgur.com/eIiZO.png
图片来源:http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
有关更多详细信息,请参阅同一篇文章。
堆中的所有对象在被引用时仍然存在。当它们不多时,垃圾收集器 (GC) 将回收它们的内存。
PermGen、Young 和 Tenured 是对象(或堆中可能存在的空间)的不同分类。
PermGen:这些对象将一直存在,它们不会被垃圾回收。有类对象,实习字符串等。我不知道那里是否有GC(当系统卸载类时......但这不是正常的事情)
Young:当一个对象被创建时,它就在这里。
Tenured:一个对象在 N 次 GC 通过后进入该分类/类别(幸存 = GC 通过,但该对象已被引用,因此无法回收)。
根据使用的 GC 和一些参数化,GC 或多或少地通过。
然后垃圾收集可以有不同的方法来管理堆中的对象。对象的这种分类有助于做到这一点。
这是另一篇关于如何调整/调整 GC 参数的优秀(虽然很长)文章,它可以帮助您了解更多:
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/
如果您遇到 GC 问题并且需要知道如何阅读 GC 日志,或者需要了解当前 GC 收集器的工作方式,那么这本书非常有用。
如果您想连接远程监控正在运行的系统以查看实时内存使用情况和 GC 运行情况,请查看此工具:
http://java.sun.com/performance/jvmstat/visualgc.html