目前,互联网上 Java 的 GC 资料要么是主要讲解理论,要么就是针对单一场景的 GC 问题进行了剖析,对整个体系总结的资料少之又少。前车之鉴,后事之师,我们搜集了内部各种 GC 问题的分析文章,并结合个人的理解做了一些总结,希望能起到“抛砖引玉”的作用。
GC技术是JAVA语言用来进行内存自动管理的,避免了手动管理带来的悬挂指针(Dangling Pointer)的问题,大大提升了开发的效率。在GC技术发展到现在,都是基于三种基础GC算法的组合或应用。
我们有时候在排查问题的时候,比较RT过高、GC耗时过长、CPU消耗过高,或多或少都会伴随着GC的产生,我们在日常工作中,需要去分析与判断,产生这些问题的根因是什么?如何才能避免这些问题的产生。
我们系统普遍使用的CMS GC的算法,我们希望通过我们对我们历史问题的分析,一起来提升GC问题的能力。
现在我们公司JAVA 8版本,所有以下的讨论都是基于这个前提进行讨论的。
GC 主要工作在 Heap 区和 MetaSpace 区(上图蓝色部分),在 Direct Memory 中,如果使用的是 DirectByteBuffer,那么在分配内存不够时则是 GC 通过 Cleaner#clean 间接管理。
简单的将,就是我们new一个对象的时候,堆内存的分配方式有两种模式。
什么是垃圾?在程序运行过程中已经使用完毕,且之后不需要在被使用的对象我们称为垃圾。
我们已经知道如何去识别虚拟机产生的垃圾,我们就需要解决如何更快速的识别到并且进行清除。
标记-清除(Mark-Sweep):看名字就很好理解,主要分两个阶段,第一阶段,通过Root Searching的方式,找出所有可达有效对象,并且进行标记;第二阶段,将没有标记的对象进行清除,这个过程对象不发生移动,不进行内存的整理。
标记-整理(Mark-Compact):第一阶段与Mark-Sweep一样;第二阶段,将可达有效对象压缩进行整理,然后清除不可达对象。
GC算法 | 优点 | 缺点 |
---|---|---|
标记-清除(Mark-Sweep) | 性能比较好,不用移动空间 | 会有碎片,特别对象比较大的情况 |
标记-整理(Mark-Compact) | 没有碎片,空间利用率高 | 性能比较低 |
复制(Copying) | 性能最好 | 空间利用率低,有大量的空间浪费 |
收集器主要分两个分代收集器与分区收集器
我们系统会使用阿里开源的arthas,以及JProfiler。
本章我们将GC的基础做了一个了解,这个只是一个皮毛还有很多东西可以深入的去了解,比如想去了解内存是如何移动的,各个算法是如何去实现的,有兴趣的都可以去了解下。本文转载《Java中常见的CMS GC问题分析与解决(一)》