原文:Hunting Memory Leaks in Java
上一篇:捕获Java内存泄露 (三)
捕获Java内存泄露 (四)
GC在JVM中如何工作的?
在我们开始分析一个有内存泄漏问题的应用之前,首先让我们看看垃圾回收在JVM中如何工作的。
JVM使用垃圾收集器的形式被称为跟踪收集器(tracing collector),它本质上是通过暂停的世界,标记所有根对象(直接被运行中的线程引用的对象),然后沿着它们的引用,标记它沿途看到的每个对象。
Java实现一个被称为分代垃圾收集器的东西,它基于分代假设,即所创建的对象中大多数都会很快被丢弃,而不被迅速收集对象可能会存活一段时间。
基于这样的假设,Java将对象分区划入为多个世代。下面是一个可视化的解释:
- 年轻代 -这是对象开始的地方,它分为两个子块:
- Eden空间 -对象在这里出生。大部分对象在这里出生在这里销毁。在这里,垃圾回收只做最小回收(Minors GCs),这是优化过的垃圾回收。当最小回收执行时,任何指向仍在使用中的对象的索引被迁移到Survivor空间(S0或S1)。
- Survivor空间(S0和S1) -从Eden空间存活下来的对象来到这里。这里分成2块,在任何时间都只有一块工作(除非我们有一个严重的内存泄露)。一个被指定为空,另一个为活动的,在每个GC周期交换。
- 终身代 -也被称为年老代。这个空间持有具有更长的生存时间的较老的对象(如果他们活得足够长,会从Survivor空间迁移过来)。当这个空间被填满,GC会做一个
Full GC
,这在性能方面的成本更高。如果这个空间的增长没有约束,JVM会抛出OutOfMemoryError - java heap space
异常。 - 永久代 -与年老代密切相关的第三代,永久代特殊是因为它持有虚拟机所需的描述在Java语言中没有对等物的对象的数据。例如,描述类和方法的对象被存储在永久代中。
Java足够聪明,它对不同的代使用不同的垃圾收集方法。年轻一代的处理方式是使用一个叫作并行新收集器(Parallel New Collector)来跟踪、复制回收器。这个收集器会停止世界(stop the world),但因为年轻代通常是比较小的,暂停是短暂的。
关于JVM分代和有关它们如何工作的更多的信息请访问Java HotSpot™ Virtual Machine文档内存管理章节。
下一篇:捕获Java内存泄露 (五)