Jvm基础知识2—垃圾回收算法

Jvm基础知识(2) - 垃圾回收算法

​ 很多人都认为GC是Java语言特有的,或者是Java语言伴随的产物。这个认识是有错误的,最早使用垃圾回收的语言是Lisp语言,Java只是让垃圾回收这个技术火起来罢了;除了Java,Go语言、Python语言也是有垃圾收集器的语言。我们都知道在C或者C++中,我们对内存是有绝对控制权的,我们掌握着一个结构体实例的生杀大权,但是程序员可能忘记回收内存最终导致生产环境内存泄漏的问题。在Java中,我们只需要使用new生成一个对象,free或者delete交给GC去做,可是我们都知道软件是不可能完美的,这就意味着Java也是有内存泄漏问题的发生,所以掌握GC相关的知识是很有必要的。

哪些运行时数据区需要GC

​ 我们都知道Java的运行时数据区分为:程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区、运行时常量池和直接内存。那么这么多运行时数据区那些需要GC收集内存,下面我们重点探讨这个问题:

  • 程序计数器、Java虚拟机栈、本地方法栈:这些运行时区域我们都知道是线程私有的,它们随着创建自己的线程而生,随着线程消亡而灭。所以这些区域是不需要GC管理的。

  • Java堆:我们都知道对象在堆中创建。也就意味着堆是GC回收的主要区域,我们听到的什么Eden区、From区、To区等,其实就是把堆按照GC处理时选用的算法划分的。

  • 方法区、运行时常量池:这两区域虽然垃圾少,但是GC也会偶尔关注它们,毕竟少不意味着没有,程序运行时间长了这两区域也可能发生内存泄漏问题。

怎么判定对象需GC被回收

  • 引用计数法:这个算法的思路就是如果有变量引用对象,那么相应的计数器就加1,对象就不会被GC所回收;相应的,当外界没有变量引用对象时,计数器就会置0,则GC将回收该对象。但是它无法解决循环引用的问题。需要知道Jvm并没有采用该算法实现GC。
  • 可达性分析算法:该算法有GC Roots,所有它不可达的对象都会被收集,所以这是一个依靠图的遍历所实现的。我们所熟知的标记-清除法标记-复制法标记-整理法都是它的分支。

四种引用关系

四种引用关系是按照GC回收的时机所划分的。

  • 强引用:平时写的类似Object obj = new Object()这样的代码。obj和它所引用对象之间的关系就是强引用。在内存不足的时候,只要引用关系存在,Jvm宁可抛出OutOfMemoryError也不会收集该对象。
  • 软引用:这种引用关系的对象GC一般不会去回收它,只有当内存不足的时候会被GC直接清理掉。
  • 弱引用:被弱引用的对象会在下轮GC中直接清除。
  • 虚引用:虚引用不会影响对象的存活时间,它只是为了在对象回收时得到一个通知所设计的,无法通过虚引用取得一个对象实例。

分代收集理论

大多数商用虚拟机都遵循分代收集理论,它建立在两个假说之上:

  • 弱分代假说:绝大多数对象时朝生夕灭的。
  • 强分代假说:熬过越多次垃圾收集的对象就越难以消亡。

所以我们所熟知的垃圾收集算法至少会把Java堆分为新生代老年代两个区域。

标记清除算法

下面时GC清理前后的内存示意图,可以看出该算法清除了可回收对象之后内存碎片较多,这对于后续对象的分配显然造成了困难,所以后续的标记复制和标记整理是基于这种不足的改进。该算法用于Eden区。

在这里插入图片描述

标记复制算法

下面是GC清理前后的内存示意图:可以看出标记复制算法划分出了两个半区,清理完毕后将剩余对象转移到另外一个半区,有点像两个队列实现栈那种感觉。但是我们知道内存是昂贵的,所以一般我们给这两个区域的空间不会太多。该算法用于FromTo区。

在这里插入图片描述

标记整理算法

下面是GC回收前后的内存示意图,可以看出该算法就是标记清除完毕之后将对象聚集到一起,那么这个时间消耗是特别大的。所以该算法用于老年区

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值