JVM耳熟能详的垃圾回收

2021-08-20  本文已影响0人  lennasu

JVM耳熟能详的垃圾回收

不管面试,还是实际开发过程中,垃圾回收真的是最重要的一块。下面我们来学习学习JVM 垃圾回收机制和回收的策略。

下面我们将从几个问题去追踪垃圾回收:

  1. 什么是垃圾,怎么会出现垃圾。
  2. 如何回收垃圾。
  3. 如何制定回收策略。

一.什么是垃圾,怎么会出现垃圾

垃圾就是内存中没有用到的对象,准确的说是在我们的堆内存中存在我们没有用的对象,内存是有限的,一旦我们的虚拟机堆内存出现内存够用,那就会出现我们非常熟悉的OOM。那我们怎么去发现这些垃圾呢。这里会引用到我们大学所学的离散数学中的图这个概念,对象之间的引用关系就可以看着是图。通过GC Root 的对象作为起始点,从这些节点开始搜索,搜索所走过的引用链,如果最终这条引用链的起始节点不是GC Root ,那么这段引用链上的所有对象就是被命名为垃圾,这就是我们需要回收的垃圾。这种方式称为可达性分析。

什么是GC Root 对象:Java 虚拟机栈引用的对象方法中静态引用指向的对象存活状态下的线程对象Native方法中JNI 引用的对象

二. 如何回收垃圾

垃圾回收会用到如下方法:标记清除、复制、标记压缩

标记清除

从GC Root 开始,将内存所有引用链遍历一遍,如果是完整的引用链就不回收,如果 没有直接或者间接 被GC Root 引用 就将这个对象回收。遍历一遍内存 把不可以回收的内存对象标记,可回收的进行标记。最后GC 的时候 回收标记可回收的对象。

缺点:容易产生内存碎片。

复制

把内存分成两块,使用的时候只使用其中的一块,当垃圾回收时将正在使用的内存中存活的对象复制到位被使用的内存块中去,然后清除正在使用的内存块中的对象。 复制的过程中清除掉垃圾对象,对引用链进行排序存到内存块中。

优点:不会参数内存碎片。

缺点:内存可用大小被缩减到一半,对象存活率高的会进行频繁的复制。

标记压缩

先使用标记清除法对内存进行回收,然后在把所有的引用链进行排序压缩到内存中的一端,清理边界外所有的空间
优点: 不会产生内存碎片,不需要两块相同的内存空间。
缺点:对局部的对象进行了移动,效率降低了不少。

三. 如何制定回收策略。

JVM 分代回收策略 Java 虚拟机根据对象存活的周期不同,把内存划分为几块,一般分为新生代,老年代,这个就是JVM 的内存分代策略。这种方式是对创建的对象会在新生代忠分配内存,生命周期比较短,如果通过几次GC 回收都依然存活下来,那就把这些对象存到老年代中。

新生代 :一般分为 Eden 区,S0区 ,S1 区 三个区, 一般按照8:1:1 来进行划分。 一般新创建的对象会分配到Eden 区,经过回收后会把仍然存活的对象复制到S0区,如果下一次GC 时Eden区,S0区满了,会把S0区的垃圾清除掉 把 S0区的对象转移到S1区中,Eden区的垃圾回收后把对象转移到刚清空的S0 区中,如此反复的进行回收方式管理内存。
老年代 当新生代S1 区中经过垃圾回收 仍然有存活的对此,此时 就会把S1区中存活的对象转移到老年代中。老年代的回收算法一般会采用标记压缩算法。

在我们编码过程中会使用到 :强引用,软引用,弱引用,虚引用

强引用垃圾回收回收不了,软引用:内存不足时会对弱引用进行回收。弱引用:只要回收时多会回收掉这块内存。虚引用:一般不会采用。

上一篇下一篇

猜你喜欢

热点阅读