java(jvm)堆内存回收流程 minor GC and major GC
无论使用何种收集器,JVM 都有两种类型的 GC 过程:
minor GC
major GC
young 年轻代使用 minor GC 过程
触发条件:JVM 无法从 Eden 空间获取分配新对象所需的内存
1. 我们假设开始时伊甸园空间上已经有对象(块 01-06)
2. 此时应用程序创建一个新对象(07)
3. JVM 试图从 Eden 空间中获取所需的内存,但是 Eden 中没有可用空间来容纳我们的对象(07),因此 JVM 触发了 minor GC
4. GC 从栈指针开始递归遍历 Eden 中的对象,使用的对象 标记为 alive (Used memory),未使用的对象标记为 garbage(Orphans 孤儿)
5. JVM 从 S0 和 S1 中随机选择一个块作为“To Space”,假设它是 S0。 GC 现在将所有活动对象移动到“To Space”,当我们移动时 S0 是空的,并将这些对象的年龄增加 1。
6. 移动后,GC 清空 Eden 空间,并从 Eden 空间给 新对象07 分配内存
7. 一段时间过去了,现在 Eden 空间上有更多的对象(块 07 到 13 标记为已用内存),应用程序创建一个新对象(14),JVM 尝试从 Eden 空间获取所需的内存,但 Eden 中没有可用空间来容纳我们的对象(14),因此 JVM 触发了第二次 minor GC
8. 依照上面的方法,标记 eden 和刚才的 S0 幸存区内的对象,
9. JVM 现在选择空闲的 S1 幸存区作为“To Space”,而 S0 变成“From Space”。
10. GC 现在将所有活动的对象从 Eden 空间和“From Space”S0 移动到“To Space”S1,并将它们的年龄增加 1。
11. 如果要移动的对象大于S1幸存区空间的容量,那么一些对象将被提前移动到“老年代”(因为幸存者空间无法增长),这个过程称为过早提升。
12. GC现在清空Eden空间和“From Space”S0,并从 Eden 空间给 新对象 14 分配内存
13. 不断的重复GC。幸存者伴随着每次的GC在 S0 和 S1 之间不断移动,并且他们的 age 不断的累加。
14. 一旦 age 达到“max-age threshold”,默认为 15,对象将被移动到“老年代 Tenured space”
old 老年代使用 major GC 过程
触发条件:
开发人员从程序中调用 System.gc() 或者 Runtime.getRunTime().gc()
没有足够的老年代空间
如果 minor GC 时不能回收足够的空间,也会触发
major GC 的过程比较简单:
1. 假设老年代没有足够的空间,触发了 major GC
2. GC 遍历老年代(如果 MajorGC 是在 minorGC 期间触发,那么还包括Eden 和 幸存区Survivor)所有对象,使用的对象 标记为 alive (Used memory),未使用的对象标记为 garbage(Orphans 孤儿)
3. GC 删除所有的 garbage(Orphans 孤儿) 并回收内存
共 0 条评论