Java中常见的CMS GC问题分析与解决(一)

2021/4/30 20:28:18

本文主要是介绍Java中常见的CMS GC问题分析与解决(一),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

Java中常见的CMS GC问题分析与解决(一)

目前,互联网上 Java 的 GC 资料要么是主要讲解理论,要么就是针对单一场景的 GC 问题进行了剖析,对整个体系总结的资料少之又少。前车之鉴,后事之师,我们搜集了内部各种 GC 问题的分析文章,并结合个人的理解做了一些总结,希望能起到“抛砖引玉”的作用。

关于GC

GC技术是JAVA语言用来进行内存自动管理的,避免了手动管理带来的悬挂指针(Dangling Pointer)的问题,大大提升了开发的效率。在GC技术发展到现在,都是基于三种基础GC算法的组合或应用。
我们有时候在排查问题的时候,比较RT过高、GC耗时过长、CPU消耗过高,或多或少都会伴随着GC的产生,我们在日常工作中,需要去分析与判断,产生这些问题的根因是什么?如何才能避免这些问题的产生。
我们系统普遍使用的CMS GC的算法,我们希望通过我们对我们历史问题的分析,一起来提升GC问题的能力。

1. GC基础知识

现在我们公司JAVA 8版本,所有以下的讨论都是基于这个前提进行讨论的。

1.1. JVM内存

java内存模型
GC 主要工作在 Heap 区和 MetaSpace 区(上图蓝色部分),在 Direct Memory 中,如果使用的是 DirectByteBuffer,那么在分配内存不够时则是 GC 通过 Cleaner#clean 间接管理。

1.2. 内存分配模式

简单的将,就是我们new一个对象的时候,堆内存的分配方式有两种模式。

  • 空闲链表(free list):通过额外的存储记录空闲的地址,将随机 IO 变为顺序 IO,但带来了额外的空间消耗。(ps:CMS)
  • 碰撞指针(bump pointer):通过一个指针作为分界点,需要分配内存时,仅需把指针往空闲的一端移动与对象大小相等的距离。(ps:Serial、ParNew)

1.3. 垃圾收集

什么是垃圾?在程序运行过程中已经使用完毕,且之后不需要在被使用的对象我们称为垃圾。

1.3.1. 垃圾识别

  • Reference Count(引用计数):对每个对象的引用进行计数,每当有一个地方引用它时计数器 +1、引用失效则 -1,引用的计数放到对象头中,当引用计数器为0的时候,认为对象已经失效,即为垃圾。之前有些文章会说,引用计数无法解决循环引用的问题,事实上已经使用Recycler算法解决了。现在现在,高并发的场景下,引用计数变更也要进行昂贵的同步操作,性能较低,现在的语言不使用。
  • Root Searching(根节点搜索法):从Root开始进行对象搜索,可以被搜索到的对象为可达对象,多次标记才能确定一个对象是否存活还是死亡。多次查询之后,所有没有被查询到的对象,都标识为垃圾,可以被回收。这个是现在java虚拟器中采用的主流的垃圾识别方案
    Root Searching

1.3.2. GC算法

我们已经知道如何去识别虚拟机产生的垃圾,我们就需要解决如何更快速的识别到并且进行清除。

  • 标记-清除(Mark-Sweep):看名字就很好理解,主要分两个阶段,第一阶段,通过Root Searching的方式,找出所有可达有效对象,并且进行标记;第二阶段,将没有标记的对象进行清除,这个过程对象不发生移动,不进行内存的整理。
    GC-MS清除

  • 标记-整理(Mark-Compact):第一阶段与Mark-Sweep一样;第二阶段,将可达有效对象压缩进行整理,然后清除不可达对象。

Mark-Compact

  • 复制(Copying):将内存空间分为两块,同一时间只会使用其中一个,每次进行回收的时候,将可达对象复制移动到另一个半区,并且清空内存里面所有的对象,并且将两个内存分区角色进行切换。
    Copying
GC算法优点缺点
标记-清除(Mark-Sweep)性能比较好,不用移动空间会有碎片,特别对象比较大的情况
标记-整理(Mark-Compact)没有碎片,空间利用率高性能比较低
复制(Copying)性能最好空间利用率低,有大量的空间浪费

1.4. 收集器

收集器主要分两个分代收集器分区收集器
收集器

1.5. 常用的分析工具

1.5.1. 命令行

  • 标准终端类:jps、jinfo、jstat、jstack、jmap
  • 功能整合类:jcmd、vjtools、arthas、greys

1.5.2. 可视化

  • JConsole、JVisualvm、HA、GCHisto、GCViewer、MAT、JProfiler

我们系统会使用阿里开源的arthas,以及JProfiler。

总结

本章我们将GC的基础做了一个了解,这个只是一个皮毛还有很多东西可以深入的去了解,比如想去了解内存是如何移动的,各个算法是如何去实现的,有兴趣的都可以去了解下。本文转载《Java中常见的CMS GC问题分析与解决(一)》



这篇关于Java中常见的CMS GC问题分析与解决(一)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程