JVM垃圾回收机制简介

本文详细介绍了JVM的垃圾回收机制,包括如何判断对象是垃圾(引用计数法与可达性分析算法)、经典的垃圾回收算法(标记清除、标记整理、复制算法)及其优缺点,以及分代垃圾回收的流程。此外,文章还探讨了不同类型的垃圾回收器,如串行回收器、吞吐量优先回收器和响应时间优先回收器(CMS),以及G1回收器的工作原理,如年轻代收集、并发标记和混合收集。通过这些内容,读者可以深入了解JVM如何管理和回收内存。
摘要由CSDN通过智能技术生成

  相信熟悉Java的开发者一定会经常听说垃圾回收这个词,可能也知道这是Java语言的一大特色(相比于C语言,Java语言会自动进行垃圾回收,这样开发者就可以不用关心内存的是否释放,大大减轻了自己的工作量,同时也能避免因忘记释放内存导致内存泄漏的情况发生。),但是并不是所有人都明白垃圾回收的工作原理。
  下面,我们将一起揭开垃圾回收的面纱,弄清楚它的工作机制。

一、如何判断对象是垃圾

1.1 引用计数法

  定义:对于一个对象,每当有一个引用指向它,计数加一,每当一个指向它的引用失效时,计数减一。计数为0的对象将被视为垃圾被回收。

  缺点:循环引用。下面A对象和B对象的计数都是1,虽然它们已经不能被使用(外界拿不到它们了),但由于计数不为0,所以也不会被当成垃圾进行回收,就会造成内存泄漏问题。
循环引用

1.2 可达性分析算法

  定义:根对象不可达的对象即是垃圾。
  根对象:GC Root,是JVM确定当前绝对不会被回收的对象。
  根可达:对象到GC Roots存在直接或间接的引用关系。

  在下图中,A对象是根对象,它直接引用B对象。B对象引用C对象和D对象,也就相当于A对象间接引用这C对象和D对象。所以B,C,D都是根可达的。E显而易见是根不可达的,所以E对象就是垃圾,需要回收它占用的内存。
根可达
  JVM中的垃圾回收器就是采用可达性分析来探索所有存活的对象。JVM通过扫描对象中的对象,看是否能够沿着以GC Root对象为起点的引用链找到该对象,找不到,则说明此对象是垃圾对象,需要回收。

二、垃圾回收算法

  找到了什么是垃圾,现在我们就需要关心怎么去回收了。JVM中垃圾回收有3种经典的方式,分别是标记清除Mark Sweep),标记整理Mark Compact)和复制Copy)。

2.1 标记清除算法

  定义:首先回收器会从根节点开始通过引用遍历堆中对象,并标记所有根可达的对象。之后回收器会从头到尾遍历堆中对象,回收掉未被标记的对象。
  优点:速度块
  缺点:容易产生内存碎片。如下图,因为垃圾对象在堆中很可能不是连续分布,所以这种算法回收的内存也会是一块隔着一块的。回收的内存块有的可能太小以至于根本用不了,就产生了内存碎片。
标记青醋和算法

2.2 标记整理算法

  定义:标记垃圾的机制和上面一样,也是以根对象,通过引用遍历堆中对象并标记。回收器第二次遍历的时候会在直接让存活对象往前移,在这个过程中,垃圾对象占用的空间会直接被覆盖,也就是了回收其内存。如下图。
  优点:没有内存碎片。
  缺点:因为要移动对象,所以速度很慢
标记整理算法

2.3 复制算法

  定义:将内存分为From区To区,回收器会将有用的对象从From区复制到To区,这样From区就整体回收掉。然后再交换FromTo的位置,To区域总是空的。如下图。
  优点:不会产生碎片
  缺点:会占用双倍的内存空间
复制算法
  在实际的垃圾回收中,JVM不会固定地只使用某一种算法,而是结合三种算法,协同工作。

三、分代垃圾回收

  首先观察JVM堆的结构,JVM把堆内存划分成了两大块:新生代老年代。新生代又划分成三个小区域:伊甸园幸存区From幸存区To。长时间使用的对象就放在老年代中,用完了就可以丢弃的对象放在新生代中。这样就可以根据区域来使用不同的垃圾回收策略。老年代垃圾回收就很久发生一次,新生代就比较频繁。
堆结构

3.1 回收流程

  • 当新建一个对象时,会将其放在伊甸园中。
    一

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值