详解 JVM 的 GC 的技术 (1)

垃圾回收机制(Garbage Collection,GC)是 java语言的特性,有了 GC,不用再像 c/c++ 那样麻烦地考虑内存的分配和释放。其实,垃圾回收机制的历史远远要比java的历史久远,因为在1960年诞生的Lisp是第一门应用垃圾回收机制的语言。虽然有了垃圾回收机制帮我们完成垃圾回收,但是我们还是得了解 GC 的运行机制,以便于在开发中排查内存泄露和内存溢出等问题,通过优化 GC 来提供应用的性能。
将 javac 编译为 class 文件加载到 JVM 中后,会分配到内存中,这里按功能将内存划分为 5 部分,分别用于存放不同内容的数据,我会在《剖析 JVM》中详细介绍。

即是对过内存了解的不多,您可能也听过内存通常分为栈内存和堆内存。栈和堆是两种不同的数据结构,我们将物理的内存抽象为这两种数据结构,便于管理内存(如何访问内存以及内存地址间的关系)。垃圾回收机制主要作用于 java 的堆(Heap)内存,堆内存也用于存放 java 对象实例,所以很多时候我们也把 java堆成为GC堆。

在程序的运行时,需要在堆内存中的对象越来越多,堆内存中没有足够的空间存放新对象。就得想办法来回收已不再用的对象,来释放堆内存的空间,那么垃圾回收机制在进行垃圾回收前,就得判断哪些实例已不再使用,哪些实例还要继续使用,我们用可达算法来判断对象是否存活。

在主流商用语言(如Java、C#)的主流实现中, 都是通过可达性分析算法来判定对象是否存活的: 通过一系列的称为 GC Roots 的对象作为起点, 静态属性和在栈内存中方法中的本地变量所引用的对象。然后向下搜索,搜索所走过的路径称为引用链/Reference Chain, 当一个对象到 GC Roots 没有任何引用链相连时, 即该对象不可达, 也就说明此对象是不可用的, 如下图: Object5、6、7 虽然互有关联, 但它们到GC Roots是不可达的, 因此也会被判定为可回收的对象。



那么我们具体如何划分堆内存的呢?现在通常做法,将内存划分一定区域,我们通常按对象存活的时间对堆内存中的对象进行划分,这就是分代算法。也是流行的 GC 算法。我们这里需要了解一个规律,就是大多数的对象都是来也匆匆去也匆匆,他们的存活是短暂的。所以我们新看 GC 是如何处理年轻代的内存的。我们将年轻代的内存再次细分为三部分 Eden 、 survivor to 和 survivor from 三个部分,首先我们还需了解我 GC 时通常是先对内存进行标记,标记出哪些内存是不可达的,也就是他们将被 GC 掉,GC 掉那些不可达(没有被引用的)对象后,在堆内存中会留下许多空位,我们还需要处理这些空位,类似 windows 的清理磁盘碎片。我们也需要清理掉这些空位,让内存连续,这个过程大家可以理解为压缩内存。







这样反复几次,如果还存活的对象反复次数超过阀值就会晋升到老年代,感谢您的支持,要获取更多更好的信息请关注我的公众号。
