JVM垃圾回收

垃圾回收


概述

java是支持自动垃圾回收的,有些语言不支持,需要手动

自动垃圾回收不是java语言首创的

垃圾回收关系的问题:

哪些区域需要回收:堆、方法区

什么时候回收:对象变为垃圾时

如何回收:

java的自动垃圾回收经过长时间的发展,已经非常强大。

什么是垃圾?

垃圾是指在运行程序中没有任何引用指向的对象

为什么需要GC(垃圾回收)?

1.如果不及时对内存中的垃圾对象进行清理,那么,这些垃圾对象所占的内存空间会一直保留到应用程序结束,被保留的空间无法被其他对象使用。甚至可能导致内存溢出

2.除了释放没用的对象,垃圾回收也可以清除内存里的记录碎片,将内存碎片进行整理(以便于创建数组,因为它需要连续的内存空间)

内存溢出和内存泄漏

内存溢出:经过垃圾回收后,内存中仍然无法存储新创建的对象,内存不够用溢出。

OutofMemory(OOM)内存溢出

内存泄漏:例如IO流 close jdbc连接 close等close资源没有关闭时,这些对象我们已经不再用了,但是垃圾回收器又不能将其判定为垃圾,这些对象就默默的占用着内存,称为内存泄漏;如果大量的此类对象存在,也是导致内存溢出的原因。

其实更应该叫内存遗漏

自动内存管理

好处:解放程序员,对内存管理更合理,自动化

不好的:对程序员管理内存的能力降低了,解决问题的能力变弱了,不能调整垃圾回收的机制。

垃圾回收相关算法

垃圾回收一般分为两个阶段,垃圾标记阶段和垃圾清除阶段

垃圾标记阶段算法

此算法的目的是:判断对象是否是垃圾对象,是否有引用指向对象

判断对象是否为垃圾对象一般有两种标记算法:引用计数算法(现在的jvm中并没有被使用)和可达性分析算法(java使用的)

1.引用计数算法:

有个计数器来记录对象的引用数量

缺点:需要维护计数器,占用空间,频繁操作需要时间开销

无法解决循环引用问题,即多个对象之间相互引用,没有其他外部引用指向它们,计数器都不为0,就不能回收,产生内存泄漏。

2.可达性分析算法(根搜索算法):

实现思路:从一些为根对象(GCRoots)的对象出发去查找搜索,与根对象直接或间接连接的对象就是存活对象,不与根对象引用链连接的对象就是垃圾对象,

GCRoots可以是哪些对象?

1.在虚拟机栈中的方法中被引用的对象

2.方法区中存储的静态属性引用指向的对象

3.作为同步锁使用的 synchronized

4.在虚拟机内部使用的对象

对象的finalization机制

已经标记为垃圾了,在对象真正被销毁回收之前,会调用一次Object类中的回调方法:finalize();

(满足复活机会后,这个对象可以复活,但是只能复活一次,下次被回收时,不会调用finalize方法,即机会只有一次)

自己不要在程序中调用finalize方法,它是留给垃圾回收器调用的

有了finalization机制的存在,在虚拟机中把对象状态分为3种:

1.可触及的:正常的对象,不是垃圾,与根对象连接的

2.可复活的: 判定为垃圾了,但是还没有调用finalize方法,在finalize法中对象可能会复活

3.不可触及的:再次判定为垃圾了,即finalize方法也被执行过了

垃圾回收阶段算法

当成功分出内存中存活对象和死亡对象后,GC接下来的任务就是执行垃圾回收,释放掉无用对象所占用的空间;

1.标记--复制算法:

将内存分为大小相同的两份空间,把当前使用的空间中存活的对象,复制到另一个空间中,将正在使用的空间中垃圾对象清除

优点:减少内存碎片

缺点:如果需要复制的对象数量多,则效率会低

适用场景:存活的对象少 ,垃圾对象多时,如新生代适合使用标记复制算法

2.标记--清除算法

清除不是真正的把垃圾对象清除掉

将垃圾对象地址维护到一个空闲列表中,后面有新对象到来是,覆盖掉垃圾对象即可。

特点:实现结构相对简单,效率低,回收后有碎片产生

3.标记--压缩算法

也叫标记--整理算法

产生背景:复制算法的高效性是建立在存活对象少,垃圾对象多的前提,是十分适用于堆中的新生代的,但是老年区中大部分都是存活对象,如果一味地使用复制算法,由于存活对象很多,复制的成本也会很高。标记--清除算法可以应用在老年区,但是因为效率较低,还会产生内存碎片等缺点,我们就产生了标记--压缩算法。

第一阶段就是标记清除算法,从根节点开始标记所有被引用对象

第二阶段将所有的存活对象压缩到内存的一端,按顺序排放。之后,清理边界外所有的空间

这个算法比标记--清除算法相比较,就是多出了一步内存碎片整理;所以这个算法又被称为标记-清除-压缩(Mark-Sweep-Compact)算法。

垃圾回收算法小结

从效率上来说,标记--复制算法可以说得上是最优的,但是他因为需要将内存分为两半,所以浪费了太多内存。为了兼顾速率,空间开销,是否移动对象这三个指标,标记--压缩算法算的上是中规中矩,单缺点就是效率太慢,因为它相比较标记--清除算法,多了一步内存碎片的整理,这也使得它不会产生内存碎片。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值