JVM主要的几种垃圾回收算法

本文详细探讨了Java的自动内存管理,包括其优势(简化开发、提高效率和可移植性)、挑战(内存占用、性能问题和垃圾回收停顿),以及垃圾回收的机制(引用计数、可达性分析和GCRoots)、方式(如标记-清除、标记-整理、复制和分代回收)和G1GC模式。
摘要由CSDN通过智能技术生成

1、Java 为什么要实现自动内存管理 ?

简化开发过程:通过内存自动管理可以避免手动分配和释放内存的麻烦,减少了内存泄漏和内存错误的风险,让研发能更专注于业务逻辑,不必纠结于内存管理的细节。

提高开发效率:垃圾回收器(Garbage Collector)能够自动追踪不再使用的对象,并释放它们占用的内存。这消除了手动跟踪和释放对象的需要,减少了开发人员的工作量,提高了开发效率。

可移植性好:研发人员不需要关心不同平台的内存管理差异,这些细节都交由虚拟机和垃圾回收器进行处理,Java的内存管理机制使得Java程序在不同的平台上运行更加容易。

2、java 自动内存管理并不是一劳永逸

       Java的自动内存管理机制(垃圾回收器和垃圾回收算法的设计),确实可以大大简化开发人员对内存管理的工作,同样也带来了一系列的问题 

内存占用和性能问题:不合适的内存使用、配置,可能导致内存占用过高或性能下降。如,长生命周期对象、内存泄漏、过频繁的垃圾回收等,都会影响应用程序的性能和稳定性。

垃圾回收停顿:虽然垃圾回收器一直都在优化减少停顿时间,但并不能完全消除。实时性要求高的系统对停顿时间很敏感

所以我们需要搞懂JVM内存管理机制,才能针对不同的场景合理使用

3、垃圾回收的机制

a、垃圾回收发生在哪里 ?

       JVM 内存模型中程序计数器、栈、本地方法栈这 3 个区域是线程私有的,与线程同生共死,不涉及回收,所以垃圾回收的就在剩下的堆和方法区中了,堆中主要回收是对象方法区的回收则主要是废弃常量和无用的类

b、什么情况下对象可以被回收?

       JVM认为一个对象不再被引用,就代表该可以被回收了,目前有两种算法可以判断该对象是否可以被回收。

引用计数算法:通过对象的引用计数器判断对象是否被引用。即每当对象被引用时,该对象的引用计数器就会 + 1;  当引用失效时,计数器再 -1。对象引用计数器值为 0 时,表示该对象不再被引用,可以被回收。引用计数算法的实现简单,判断效率也很高,但它存在对象之间循环引用的问题

可达性分析算法:  在垃圾回收时,以 GC Roots 对象为根对象开始遍历对象图,确定哪些对象是可达的(即不会被回收),而哪些对象是不可达的(即可被回收)。目前 HotSpot 虚拟机采用的就是这种算法。

c、哪些是 GC Roots 对象 ?

虚拟机栈(栈帧中的本地变量表)中引用的对象:当前线程中方法调用链上的所有对象。

方法区中的类静态属性引用的对象:被类声明为静态变量的对象。

方法区中常量引用的对象:被常量池中的常量引用的对象。

本地方法栈中引用的对象:在Java代码中调用本地方法后,本地方法中引用的对象

       GC Roots 本身是不可被回收的,它们的存在保证了从根节点出发的对象的可达性。垃圾回收器通过追踪GC Roots对象的引用链,可以确定哪些对象是可达的,而哪些对象是不可达的,从而进行垃圾回收操作。

4、垃圾回收的三种方式

a、标记-清除算法(Mark and Sweep)

       把垃圾对象所占据的内存标记为空闲内存,并记录在一个空闲列表(free list)中。当需要新建对象时,内存管理模块便会从该空闲列表中寻找空闲内存,并划分给新建的对象。该回收方式的原理非常简单,但会带来俩个缺点

内存碎片化:由于 Java 虚 拟机的堆中对象必须是连续分布的,因此可能出现总空闲内存足够,但是无法分配的极端情

内存分配效率低:如果是一块连续的内存空间,那么我们可以通过指针加法 (pointer bumping)分配。但对于空闲列表,Java 虚拟机则需要逐个访问列表中的项,来查找能够满足新建对象的大小的空闲内存

b、标记-整理算法(Mark and Compact)

       在标记阶段(Mark)也会标记所有可达对象。然后,在整理阶段(Compact),将存活的对象压缩(Compact)到堆的一端,以释放不连续的内存空间。这种做法能够解决内存碎片化的问题,但代价是压缩算法的性能开销。

c、复制(copy)

       把内存区域分为两等分,分别用两个指针 from 和 to 来维 护,并且只是用 from 指针指向的内存区域来分配内存。当发生垃圾回收时,便把存活的对 象复制到 to 指针指向的内存区域中,并且交换 from 指针和 to 指针的内容。复制这种回收方式同样能够解决内存碎片化的问题,但是它的缺点也极其明显,即堆空间的使用效率极其低下。

d、分代回收算法(Generational)

        分代算法基于对象的生命周期将堆内存分为不同的代,如新生代和老年代。新生代中的对象通常具有较短的生命周期,而老年代中的对象具有较长的生命周期。不同代使用不同的垃圾回收算法,以便更好地适应对象的特性和内存使用模式。

G1的三种GC模式

young GC:当所有 eden region 被消耗无法再申请时触发一次young GC,活对象被拷贝到survivor region 或者晋升到 old region

mixed GC:回收整个young region,同时回收一部分old region。老年代占用达到一定阈值的时候触发

full GC:对象内存分配过快,mixed GC来不及回收,导致老年代被填满,会触发一次full GC

       JVM在应用垃圾回收器时往往会综合上述几种回收方式,综合它们优点的同时规避它们的缺点,达到比较优的内存管理方式

  • 19
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值