[JVM基础]-- 垃圾回收基础(GC相关)

一. 垃圾的定义

1. 什么是垃圾

当内存中的某一个对象无法找到任何引用的时候,这个对象就是一个垃圾对象。

2. 什么是内存泄露

内存泄露(memory leak),是指程序中已动态分配的堆内存由于某种原因程序未将其释放或无法释放,造成了内存的浪费,导致程序运行速度减慢甚至程序崩溃等严重后果。

3. 什么是STW

STW即stop the world ,指的是JVM进行GC时会暂停所有业务线程。

二. 垃圾查找算法

1. 引用计数算法(reference count)

(1) 定义

给每一个对象添加一个引用计数器,t每当有新的引用时,计数器+1,引用结束后计数器-1。任何时刻计数器为0的对象都是不被引用的。

(2) 特点

优点:
1. 引用计数算法在回收垃圾时具有实时性。当一个对象的引用为0的时候会被直接回收,无需等待特定时间就可以释放内存。
缺点:
1.当出现对象之间循环引用的时候,垃圾回收期无法确定这些对象是否是垃圾,因此无法回收循环引用的对象。(内存泄漏)

2. 根可达算法(root searching)

(1)定义

从GC Roots节点(起始节点)出发向下搜索,如果没有任何引用链(既GC root不可达),则证明此对象不可用
在这里插入图片描述

(2)哪些对象可以作为GC Root

  1. 虚拟机栈中局部变量(也叫局部变量表)中引用的对象
  2. 方法去中类的静态变量,常量引用的对象
  3. 本地方法栈中JNI(native方法)引用的对象

(3) 特性

tracing GC的本质是通过找出所有活对象来把其余空间认定为“无用”,而不是找出所有死掉的对象并回收它们占用的空间。GC roots这组引用是tracing GC的起点。要实现语义正确的tracing GC,就必须要能完整枚举出所有的GC roots,否则就可能会漏扫描应该存活的对象,导致GC错误回收了这些被漏扫的活对象。

三. 垃圾回收算法(GC Algorithms)

1. 标记清除算法(mark-sweep)

(1)定义

将需要清除的对象标记出来,清除掉。

(2)实现

标记清除算法的实现分为两个阶段:

  1. 标记阶段:标记出存活对象
  2. 回收阶段:回收未被标记对象所占有的空间
    具体流程如下图:
    在这里插入图片描述

(3) 特性

优点:
只对存活的对象进行标记。标记完毕后在扫描整个空间中未被标记的对象进行回收。该算法不需要进行对象的移动,只需对不存活的对象进行处理,效率高。
缺点
因为直接回收掉了不存活对象,未对内存进行整理,因此会产生内存碎片。内存碎片较多时,当大对象进入内存空间,无法为期分配足够的内存会提前触发GC。

2.复制算法(copy)

(1)定义:

讲内存一分为二,每次使用一个区域。当触发gc时,将存活对象复制到另一区域,清除原区域。

(2)实现

它开始时把堆分成 一个对象 面和多个空闲面, 程序从对象面为对象分配空间,当对象满了,基于copying算法的垃圾 收集就从根集合(GC Roots)中扫描活动对象,并将每个 活动对象复制到空闲面(使得活动对象所占的内存之间没有空闲洞),这样空闲面变成了对象面,原来的对象面变成了空闲面,程序会在新的对象面中分配内存。
在这里插入图片描述

(3)特性

优点

  1. 只扫描一次,效率高。
  2. 实现方式为复制移动对象,不会产生内存碎片

缺点:

  1. 因为将内存分为两个区域,其中一个区域保持空闲,因此内存浪费大
  2. 复议移动对象的时候会调整对象引用

3. 标记整理(mark-compack)

(1)定义

标记清除算法的优化实现,清除垃圾对象的同时压缩空间。

(2) 实现

该算法标记阶段和Mark-Sweep一样,但是在完成标记之后,它不是直接清理可回收对象,而是将存活对象都向一端移动,然后再清理掉无用对象
在这里插入图片描述

(3)特性

优点:
1.因为对空间进行了整理,因此不会产生内存碎片。
缺点
1.因为扫描了两次,并且在清除的基础上还增加了整理,因此时间成本高。

面试题

1. 根可达算法是深度优先算法还是广度优先算法?

年轻代偏向于广度优先,老年代偏向于深度优先。

猜你喜欢

转载自blog.csdn.net/xiaoai1994/article/details/109640045