了解JVM中的GC

Posted XeonYu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了了解JVM中的GC相关的知识,希望对你有一定的参考价值。

上一篇:
了解 JVM和JVM内存结构(JVM运行时数据区)

上一篇博客我们对JVM的内存结构有了一个简单的认识,我们都知道Java是有GC自动对内存进行回收的,那GC到底是怎么工作的,对象在什么时候会被回收呢?
本篇博客我们就来了解一下GC;

GC

Garbage Collector :垃圾收集器
顾名思义,就是专门收集垃圾的。

什么是垃圾

简单来讲,没有任何引用指向的对象(没有任何用处的对象),就是垃圾,要被回收掉。

怎么判断一个对象是不是垃圾

引用计数器法

简单将就是一个对象每被另一个对象所引用,则计数器+1,解除引用后-1,如果一个对象的引用计数器为0,则视为垃圾。

根可达性分析法

根:又叫做 GC roots

先来看看JVM内存模型中哪些属于GC roots

  • 虚拟机栈
  • 本地方法
  • 常量池
  • 方法区中的静态变量等

通过GC roots 根节点一直往下找,能找到的引用的对象都不是垃圾,其他的就都是垃圾。

如图所示:

其中,蓝色的就会被标记为非垃圾对象。其它的自然而然就是垃圾对象了。


常见的垃圾回收算法

标记清除法

先对内存扫描一遍,将是垃圾对象所在的区域标记一下,然后进行回收。

缺点:会产生不连续的空间

图示如下

拷贝清除法
将内存一分为二,只用一半的空间存放对象,当前使用的一半空间需要做内存回收时,先对这一半的空间进行扫描,将不是垃圾的对象拷贝到另一半空间,然后对现在这一半的空间整体进行回收。
当另一半满了需要做内存回收时,则再走一遍上述过程,将不需要回收的对象拷贝到这一半,然后直接回收掉另一半空间。
周而复始。

图示如下:

优点:不会产生内存碎片
缺点:浪费空间

标记压缩法

在扫描的时候,将标记为垃圾的区域进行回收,然后把存活的对象挪到当前区域,同时遇到未使用的空间时,如果后面还有存活对象,则也挪到当前可使用区域。

图示如下:

优点:不会产生内存碎片
缺点:效率相对较低


JVM 分代模型

了解完常见的回收算法后,我们来看一下JVM的分代模型
JDK1.8 默认垃圾回收器为例

JVM 将堆内存分为两代,年轻代老年代
默认情况下,年轻代占堆大小的三分之一,老年代占堆大小的三分之二

如图所示

年轻代中又分为伊甸区幸存者区,其中幸存者区又分为S0S1区。伊甸区占年轻代大小的8/10,S0和S1分别占1/10

其中,新生代中的回收算法使用的是 拷贝清除法 ,老年代中的回收算法是标记压缩法

我们来看一下一个对象从产生到被回收大概的过程是怎样的

先看一下新创建的对象是如何存放到堆中的,如图所示

full gc: 整个堆的gc(包含年轻代和老年代),由于使用的是标记压缩法,效率较低,代价较大
minor gc: 也叫young gc:对年轻代进行gc,默认使用复制清除法,效率高

总结:新创建的对象会先往伊甸区中存放,绝大多数情况下都能放下,除非对象特别大且伊甸区放不下,会先对伊甸区进行一次minor gc,gc过后如果伊甸区能放下,放入伊甸区,还是放不下的话,则会尝试向老年代中存放,如果老年代也放不下,则会先进一次full gc, 回收过后如果老年代空间足够,放入老年代,老年代也放不下的话,报OOM异常。

再来看下GC的过程中是怎么处理对象的

当伊甸区容量达到一定的条件或者JVM虚拟机空闲时,会触发minor gc

首次回收时:会先使用 根可达性分析法 标记伊甸区中的非垃圾对象,然后将这些对象复制到S0区域,然后将整个伊甸区全部回收。

再次回收:先使用 根可达性分析法 找出伊甸区和S0区中非垃圾对象,将这些对象复制到S1区,然后直接将伊甸区和S0区全部回收

再次回收:先使用 根可达性分析法 找出伊甸区和S1区中非垃圾对象,将这些对象复制到S0区,然后直接将伊甸区和S1区全部回收

周而复始…

大致上就是使用上面的拷贝清除法来回收年轻代中的内存。需要注意的是,如果一个对象经历过15次(默认值是15)minor gc还没有被回收掉,就会将该对象移至老年代

老年代的回收就是上面的标记压缩法了,需要注意的是,当老年代没有足够的内存存放数据时,会先进行一次full gc,full gc之后如果仍然没有足够的空间存放对象,则会报出OOM异常。

一般Java开发工程师所说的JVM调优,实际上就是通过修改一些参数,以达到尽可能的减少full gc的次数的目的。

好了,到这里,我们对JVM内存回收算是有了一个基本的认识了。


如果你觉得本文对你有帮助,麻烦动动手指顶一下,可以帮助到更多的开发者,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!

以上是关于了解JVM中的GC的主要内容,如果未能解决你的问题,请参考以下文章

了解JVM中的GC

java之JVM学习--简单了解GC算法

初步了解JVM第三篇(堆和GC回收算法)

JVM_GC了解(转发)

Java学习之二(线程(了解) JVM GC 垃圾回收)

深入了解jvm-2Edition-GC与内存分配策略