在 Java 8 中,永久代(PermGen)被**元空间(Metaspace)**取代了,但我们仍然可以探讨老年代(Old Generation)和永久代的垃圾回收算法。
1. 老年代(Old Generation)
- 标记-清除-压缩算法(Mark-Sweep-Compact): 在 Java 8 中,老年代默认使用的是标记-清除-压缩算法。这一算法可以分为三个阶段:
- 标记阶段:标记出所有存活的对象。
- 清除阶段:清理掉未被标记的、不可达的对象。
- 压缩阶段:压缩内存,将存活对象紧密地排列在一起,避免内存碎片化。
2. 永久代(PermGen)与元空间(Metaspace)
- 在 Java 7 及之前,永久代使用标记-清除-压缩算法来管理类的元数据、静态变量以及字符串常量池。
- Java 8 引入了 Metaspace,用以替代 PermGen。Metaspace 使用的是本地内存,而不是堆内存。元空间根据应用程序的需要动态扩展,所以不像 PermGen 那样依赖垃圾收集的频繁清理。
总结:
在 Java 8 中:
- 老年代默认使用的是标记-清除-压缩算法,包括标记、清理和压缩阶段。
- 永久代被元空间取代,元空间使用了本地内存,并且依赖于动态扩展机制,而不再频繁依赖垃圾收集。
这种算法不仅能有效回收内存,还能通过压缩避免内存碎片,提高内存管理的效率。
在 Java 8 中,确实有几个重要的变化,特别是在老年代(Old Generation)和永久代(PermGen)的管理方式上,以下是详细解释:
1. 老年代(Old Generation)
- 位置:老年代依然是堆(Heap)内存的一部分。堆内存在 Java 中是分为两部分的:新生代(Young Generation)和老年代(Old Generation)。当对象从新生代晋升到老年代后,它们会在这里停留更长的时间。
- 算法:老年代默认使用**标记-清除-压缩(Mark-Sweep-Compact)**算法。随着对象生命周期的延长,存活对象较多,因此通过标记清除之后,还会进行压缩来减少内存碎片。
2. 永久代(PermGen)与元空间(Metaspace)
- 在 Java 8 之前,**永久代(PermGen)也是堆内存的一部分,负责存储类的元数据、静态变量、方法区等信息。然而在 Java 8 中,永久代被元空间(Metaspace)**所替代。
- 元空间(Metaspace):
- 本地内存:元空间与堆内存不同,它不再使用堆空间,而是使用本地内存(native memory),即 JVM 运行所在的进程内存。这意味着元空间的大小不是固定的,而是随着应用的需求自动扩展。
- 动态扩展:元空间根据需要自动分配内存,默认情况下不会造成内存溢出问题(不像 PermGen 那样有固定大小),并且依赖于 JVM 自身的垃圾回收机制来释放未使用的类元数据。
总结:
- **老年代(Old Generation)**仍然存在于堆内存中,负责存储长期存活的对象。
- 永久代(PermGen)在 Java 8 中被元空间(Metaspace)取代,元空间使用的是本地内存,不再占用堆内存。这提升了类元数据的管理效率,避免了之前版本中 PermGen 空间不足的问题。