【JVM】GC垃圾回收[精简版]

JVM内存区域

在这里插入图片描述

判断需要对哪些对象进行垃圾回收(主要关注于Java堆)

有两种方法:

  • 引用计数法(Reference Counting)(主流java虚拟机不使用此方法)
    给对象添加一个引用计数器,每次引用计数器值加1;当引用失效时,计数器值就减1;当计数器为0时,对象就是不可能再被利用的。
    无法解决对象之间相互循环引用的问题
  • 可达性分析法(Reachability Analysis)
    通过一系列称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。
    在这里插入图片描述
    可作为GC Roots的对象包括下面几种:
  • 虚拟机栈(栈帧中的本地变量表)中引用的对象。
  • 方法区中类静态变量属性引用的对象。
  • 方法区中常量引用的对象。
  • 本地方法栈中JNI(Native方法)引用的对象
  • 虚拟机内部的引用,如基本数据类型对应的Class对象
  • 所有被同步锁(synchronized)持有的对象

GC管理的区域是Java堆,虚拟机栈、方法区、本地方法栈不被GC所管理,因此这些区域内引用的对象作为GC Roots,是不会被GC回收

引用类型:强、软、弱、虚

reference类型的数据中存储的数值代表的是另一块内存的起始地址,称该reference数据是代表某块内存、某个对象的引用
扩展引用的概念:强引用、软引用、弱引用、虚引用

  • 强引用:传统的引用定义,Object obj = new objec()
  • 软引用:有用但非必需的对象。在发生内存溢出异常前,这些对象被列入回收范围中进行第二次回收。如果回收后内存仍旧不足,会抛出内存溢出异常。
  • 弱引用:描述非必需对象、强度比软引用更弱,关联的对象生存到下一次垃圾回收为止
  • 虚引用:无法通过虚引用来取得一个对象实例。设置虚引用关联的目的是这个对象被收集器回收时得到系统通知
    在这里插入图片描述

可达性分析算法判断是否回收对象

宣告一个对象的死亡(回收)需要经过两次标记:

  • 对对象进行可达性分析后发现没有与GC Roots相连接的引用链,那么将被第一次标记。随后进行一次筛选,判断该对象是否有必要执行finalize()方法。
    • 如果对象没有覆盖finalize()方法或finalize()方法已经被虚拟机调用过了,那么虚拟机将这两种情况视为“没有必要执行”
    • 如果对象被判定为有必要执行finalize()方法,那么该对象会被放置在一个名为F-Queue队列中,稍后由一个虚拟机自动建立的、低调低优先级的Finalizer线程去执行它们的finalize()方法。【这里的执行,指虚拟机会触发这个方法开始运行,但并不承诺等待它运行结束。(避免执行缓慢和死循环)】
  • finalize()方法是对象逃脱死亡命运的最后一次机会,稍后收集器将对F-Queue中的对象进行二次小规模的标记,如果对象要在finalize()中成功拯救自己,只需要重新与引用链上的任何一个对象建立关联即可。

注:finalize()是Object中的方法,当垃圾回收器将要回收对象所占内存之前被调用,即当一个对象被虚拟机宣告死亡时会先调用它finalize()方法,让此对象处理它生前最后事情(对象可以趁这个时机挣脱死亡的命运)

垃圾收集算法与分代收集理论

可划分为两种类型:

  • 引用计数式垃圾收集(Reference Countiong GC)【主流Java虚拟机未涉及】
  • 追踪式垃圾收集(Tracing GC)

分代收集理论

当代虚拟机垃圾收集齐遵循了分代收集(Generational Collection)理论进行设计。
建立在两个分代假说至上:

  • 弱分代假说(Weak Generational Hypothesis):绝大多数对象朝生夕灭
  • 强分代假说(Strong Generational Hypothesis):熬过月多次垃圾收集的对象越难以消亡

拓展假说:

  • 跨代引用假说(Integenerational Reference Hypothesis):跨代引用相对于同代引用来说仅占少数
    【根据这条假说,可以再新生代建立全局数据结构(记忆集,Remembered Set),把老年代划分成若干小块,标识出老年代哪一块内存会出现跨代引用。发生Minor GC时。包含了跨代引用的小块内存里的对象会被加入GC Roots进行扫描】

分代假说奠定了垃圾收集的原则:收集齐将Java划分出不同的区域,将回收对象依据其年龄(对象熬过垃圾收集过程的次数)分配到不同的区域中存储。【如Minor GC、Major GC、Full GC】

垃圾收集算法详述

  • 标记-清除算法
  • 标记-复制算法
  • 标记-整理算法
标记-清除算法

算法分为标记和清除两个阶段:

  • 标记所有需要回收(或存活)的对象。
  • 标记完成后,清除所有被标记(未被标记)的对象。

缺点:

  • 标记清除两个过程执行效率随对象数量增长而增长
  • 内存空间碎片化【弥补方式:分区空闲分配链表】
标记-赋值算法

半区复制的垃圾收集算法,按容量大小划分为相等大小的两块,每次使用其中一块,当一块内存用完了,就将还活着的对象赋值到另外一块上面,再把已使用过的内存空间一次清理掉。

缺点:

  • 如果内存中多数对象都是存活的,会产生大量的内存空间复制的开销【如果多数可回收,算法需要复制的就是占少数的存活对象】
  • 空闲浪费多

注:改进
一块Eden空间和两块小的Survivor空间(8:1:1),每次分配内存只使用Eden和其中一块Survivor。垃圾收集时,将Eden和Survivor中仍存活的对象一次性复制到另外一块Survivor空间上,然后清理掉Eden和已使用过的那块Survivor空间。
【Survivor空间不够则需要老年代进行担保】

标记-整理算法

标记过程与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向内存空间一端移动,然后直接清理掉边界以外的内存。

缺点:

  • 需要必须暂停用户程序

中和方式:

  • 平时使用标记-清除算法,暂时容忍内存碎片的存片,直到内存空间的碎片化程度已经大到影响对象分配时,在采用标记-整理算法收集一次,以获得规整的内存空间。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是几个 JVM 垃圾回收相关的面试题及其答案: 1. 什么是垃圾回收垃圾回收是指在程序运行过程中,自动回收不再使用的内存空间,以提高内存利用率和程序的性能。 2. JVM垃圾回收机制是什么? JVM垃圾回收机制采用分代收集算法,将内存分为新生代和老年代,分别采用不同的垃圾回收算法来回收内存。 3. 新生代垃圾回收器有哪些? 新生代垃圾回收器主要有 Serial、ParNew、Parallel Scavenge 等。 4. 老年代垃圾回收器有哪些? 老年代垃圾回收器主要有 Serial Old、Parallel Old、CMS、G1 等。 5. 什么是对象的引用计数算法? 引用计数算法是一种简单的垃圾回收算法,它通过记录每个对象被引用的次数,当引用次数为 0 时,即可将该对象回收。 6. 引用计数算法的缺点是什么? 引用计数算法的缺点是无法处理循环引用的情况,如果两个对象之间相互引用,它们的引用计数一直不为 0,导致无法回收。 7. 什么是标记-清除算法? 标记-清除算法是一种常见的垃圾回收算法,它将垃圾回收分为两个阶段:标记阶段和清除阶段。在标记阶段,标记所有活跃对象,将其打上标记;在清除阶段,清除所有未标记的对象。 8. 标记-清除算法的缺点是什么? 标记-清除算法的缺点是产生大量的内存碎片,导致内存利用率降低。 以上是一些常见的 JVM 垃圾回收面试题及其答案,希望能对你有所帮助。在面试过程中,需要根据具体的问题进行回答,同时也需要对垃圾回收机制和算法有清晰的认识,才能更好地回答相关的问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值