jvm垃圾收集算法

一、什么是垃圾回收

程序的运行必然需要申请内存资源,而一些无效的资源如果不及时的清理回收,就会一直占用内存,最终导致内存溢出,所以把这些无效的资源称之为垃圾,而清理这些垃圾的动作就叫做垃圾回收。但是垃圾回收之前必须要先确认这些对象是否已经真的死去,即不可能再被任何途径使用的对象。判断方法一般有下面这两种。

引用计数算法
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器加1,当引用失效时,计数值就减1,任何时刻当计数值为0的对象就是
不可能再被引用的。虽然引用计数算法实现简单,判断效率也很高,但是主流的java虚拟机都没有选用这个方法来管理内存,主要的原因
就是因为它很难解决对象之间循环引用的问题。比如有两个对象A、B 他们都有个字段 o ,进行赋值 让 A.o = B; B.o = A;除此之外,
这两个对象再无任何引用,其实这两个对象已经不可能再被访问引用了,但是用引用计数器无法回收他们。
还有就是即使内存够用,他也会去进行计数器的加减,会浪费cpu资源。
可达性分析算法
在一些主流语言(java,C#等)都是用可达性分析算法来判断对象是否存活的。
这个算法的基本思想是通过一系列的称为 “GC Roots” 的对象作为起始点,从这些节点往下搜索,搜索走过的路径称为引用链,当一个对象
到GC Roots 没有任何引用链相连时,就证明这个对象是不可用的。

就像上面的图一样,虽然 Object 5、Object 6、Object 7 之间相互引用,但是他们到GC Roots是不可达的,所以他们将会被判断为可回收对象。

在java语言中,可以作为GC Roots的对象有:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象。
  • 方法区中类静态属性引用的对象。
  • 方法区中常量引用的对象。
  • 本地方法栈中native方法引用的对象。

二、垃圾回收(收集)算法

2.1 标记 - 清除算法

这是最基础的收集算法,分为标记和清除两个阶段,首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
这种收集算法主要有两个不足:
一、效率问题,标记和清除效率都不高。
二、空间问题,标记清除后会产生大量的内存碎片,内存碎片太多的话会引起以后程序需要分配一个较大对象的时候,无法找到足够的连续的内存来存储而不得不再一次触发垃圾回收。

2.2 复制算法

为了解决效率问题,复制收集算法出现了,他将可用内存按照容量划分为大小相等的两块,每次只使用其中一块,当这一块内存使用完之后,就将还存活着的对象复制到另一块内存上,然后原来的那一半里的对象全部进行回收。缺点显而易见,内存被缩小一半。堆内存中的两个Survivor区域就是使用的这种算法。
HotSpot虚拟机默认Eden 和其中一个Survivor区的比例为8:1也就是说,每次新生代中的可用内存空间为百分之90(80+10),只有百分之10的内存会被闲置(浪费)。如果回收的对象多于百分之10的话,就需要进行
分配担保
了。
分配担保:就好比去银行借钱,如果你不能按时还款,也就是没钱的时候,会从你担保人的账户扣钱,虚拟机也一样,如果另一块Survivor区域没有足够的空间存放上一次新生代收集的存活对象的话,这些对象将直接通过分配担保进入老年代。

2.3 标记 - 整理算法

标记 - 整理算法的标记过程和 标记 - 清除 算法是一样的,只不过标记完不是立即清除,而是进行整理,所有存活的对象都向一端移动,然后直接清理掉其他内存。

2.4 分代收集算法

分代收集算法是根据垃圾回收对象的特点进行选择,在jvm中,年轻代每次垃圾收集都会有大量对象死去,只有少量存活,可以使用复制算法,而老年代中,对象存活率较高,没有多余内存,则使用标记清除算法或者标记整理算法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值