jvm内存回收

一、GC是通过对象是否存活来决定是否进行回收,判断对象是否存活主要有两种算法:引用计数算法、可达性分析算法
①引用计数算法
引用计数的算法原理是给对象添加一个引用计数器,每被引用一次计数器加1,引用失效时减1,当计数器0后表示对象不在被引用,可以被回收了,引用计数法简单高效,但是存在对象之间循环引用问题,可能导致无法被GC回收,需要花很大精力去解决循环引用问题
②可达性分析算法
可达性分析的算法原理是从对象根引用(堆栈、方法表的静态引用和常量引用区、本地方法栈)开始遍历搜索所有可到达对象,形成一个引用链,遍历的同时标记出可达对象和不可达对象,不可达对象表示没有任何引用存在,可以被GC回收

二、内存回收算法主要有标记-清除、停止-复制、标记-整理,不同算法使用不同的场景,总体来说停止-复制算法适合对象存活时间短,存活率低的新生代,标记-清除和标记-整理算法适合对象存活时间长,存活率高的老年代
①标记-清除(Mark-Sweep)
通过可达性分析算法标记所有不可达对象,然后清理不可达对象。这种算法会形成大量的内存碎片
②停止-复制(Stop-Copy)
将新生代内存按照8:1:1的比例分为一个eden区和两个survivor(survivor0,survivor1)区,回收时先将eden区存活对象复制到一个survivor0区,然后清空eden区,当这个survivor0区也存放满了时,则将eden区和survivor0区存活对象复制到另一个survivor1区,然后清空eden和这个survivor0区,此时survivor0区是空的,然后将survivor0区和survivor1区交换,即保持survivor1区为空, 如此往复,当survivor1区不足以存放 eden和survivor0的存活对象时,就将存活对象直接存放到老年代(这时我们可能回想,若是老年代也满了咋办,若是老年代也满了就会触发一次Full GC,也就是新生代、老年代都进行回收,若是内存还不够呢。。。,还不够那不废话了吗,OutOfMemory,不陌生吧哈哈)。从停止-复制算法的原理上我们可以看到,这种算法对于存活率较低的对象回收有着非常高的效率,而且不会形成内存碎片,但是会浪费一定的内存空间,适合对象存活率较低的新生代使用,如果在对象存活率较高的老年代采用这种算法,那将会是一场灾难
③标记-整理(Mark-Compact)
通过可达性分析算法标记所有不可达对象,然后将存活对象都向一个方向移动,然后清理掉边界外的内存。这种算法是将存活对象向着一个方向聚集,然后将剩余区域清空,这种算法适合对象存活率较高的老年代

三、GC回收机制:分代收集算法
JVM内存收集算法基本上都是采用分代收集算法,即将内存划分为新生代、老年代,也有人把方法区算做永久代
①新生代
对象被创建时,内存分配都是发生在新生代(大对象直接分配在老年代),绝大多数对象都是朝生夕灭,创建后很快就会不在使用,变为不可达的对象,被GC回收掉。新生代的对象存活率很低(到底有多低?研究表明有高达98%的对象创建后很快就消亡,想象一下平时编程,除了全局变量,局部变量在退出调用方法后还有几个能存活),存活时间都很短,新生代发生的GC也叫做Minor GC,MinorGC发生频率比较高(不一定等Eden区满了才触发)
②老年代
当对象在新生代发生了多次Minor GC后仍然存活的对象即进入老年代,老年代的对象比新生多很多,当然了内存比新生代也大很多(大概比例是1:2,即新生代占用堆内存总量的1/3),当老年代内存满时触发Major GC即Full GC,Full GC发生频率比较低,老年代对象存活时间比较长,存活率标记高
一般来说我们所说的GC都是发生在新生代和老年代,新生代对象存活时间短,存活率低一般采用停止-复制算法,老年代对象存活时间长,存活率高,一般采用标记-整理、标记-清楚算法,具体采用何种算法和具体采用的垃圾收集器有关

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值