JVM听课随记06 GC 四大算法

1.如何判断Java对象是否存活

1.1 引用计数算法

引用计数算法是给每个对象设置一个计数器,当有地方引用这个对象的时候的,计数器+1,当引用失效的时候,计数器-1,当计数器为0的时候,JVM就认为该对象不再被使用,是垃圾了。

引用计数实现简单,效率高;但是不能解决循环引用的问题(A对象引用B对象,B对象又引用A对象,但是A,B对象已不被任何其他对象引用),同时每次计数器的增加和减少都带来了很多额外的开销,所以在JDK1.1之后,这个算法已经不再使用了。

在这里插入图片描述

1.2 根搜索方法

根搜索方法是通过一些GCRoots对象作为起点,从这些节点开始往下搜索,搜索通过的路径成为引用链(ReferenceChain),当一个对象没有被GCRoots的引用链连接的时候,说明这个对象是不可用的。(这个不重要暂时不做详解)

2. 复制算法:适用于新生代

2.1 原理分析

虚拟机把新生代分为了三部分:1个Eden区和2个Survivor区(分别叫fromto),默认比例为8:1:1。

一般情况下,新创建的对象都会被分配到Eden区(一些大对象特殊处理),这些对象经过第一次的Minor GC后,如果仍然存活,将会被移到Survivor区。对象在Survivor区每熬过一次Minor GC,年龄就+1,当它的年龄增加到一定程度时(默认是15,通过-XX:MaxTenuringThreshold来设定参数),就会被移动到老年代去。

因为新生代中的对象基本都是朝生夕死(被GC回收率90%以上),所以在新生代的垃圾回收算法使用的是复制算法。

复制算法的基本思想就是将内存分为两块,每次只有其中一块(from),当这一块内内存用完,就将活着的对象复制到另一块上。

举一个例子说明:在GC开始的时候,对象只会存在于Eden区,和名为from的Survivor区,Survivorto是空的。紧接着进行GC,Eden区中所有存活的对象都会被复制到to,而在from区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值(默认15)的对象会被移动到老年代中,没有达到阈值的对象会被复制到to区域。经过这次GC后,Eden区和from区已经被清空。这个时候,from和to会交换他们的角色,也就是新的to就是上次GC前的from,新的from就是上次GC前的to。不管怎样,都会保证名为to的Survivor区域是空的。Minor GC会一直重复这样的过程,直到to区被填满,to区被填满之后,会将所有对象移动到老年代中。
 在这里插入图片描述

 注意:-XX:MaxTenuringThreshold,设置对象在新生代中存活的次数。

因为Eden区对象一般存活率较低,一般的,使用两块10%的内存作为空闲和活动区间,而另外80%的内存,则是用来给新建对象分配内存的。一旦发生GC,将10%的from活动区间与另外80%中存活的Eden区对象转移到10%的to空闲区间,接下来,将之前90%的内存全部释放,以此类推。

在这里插入图片描述

上边动画中,Area空闲代表to,Area激活代表from,绿色代表不被回收的,红色代表被回收的。

2.2 优缺点

优点:不会产生内存碎片,效率高。

缺点:消耗内存空间。

如果对象的存活率很高,我们可以极端一点,假设是100%存活,那么我们需要将所有对象都复制一遍,并将所有引用地址重置一遍。复制这一工作所花费的时间,在对象存活率达到一定程度时,将会变的不可忽视。

所以从以上描述不难看出,复制算法要想使用,最起码对象的存活率要非常低才行,而且最重要的是,我们必须要克服50%内存的浪费。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值