GC初识

垃圾回收(GC)指的是释放那些已经死亡或者长时间未使用的对象占用的内存空间,防止内存泄露。

1. Java不像C++需要程序媛自己回收垃圾,它交由管家JVM去回收垃圾,属于吃了饭擦擦嘴就走人类型。问题来了:哪些对象属于垃圾呢?JVM怎么辨别垃圾呢?引用计数法和可达性分析算法

1.1 引用计数法,对象头中有个区域存储被引用的次数count,每次被引用时,count++,删除引用(不指向它时),count--,若是count为0,说明这是垃圾了。此方法分摊到整个应用程序的运行中,而不是挂起整个应用的运行。但是要是存在如下情况:堆内部俩对象互相引用(循环依赖),栈区无引用(置空),那么堆区这俩哥们就永远回收不掉了。

1.2 可达性分析算法,从引用链对象GC Roots(作为起点)一直往下搜索,到此对象有无一条可达的路径,若有,则是存活对象,否则就是垃圾。问题是:哪些能号称GC Root呢?

“四大天王”:

         栈(本地变量表)中引用的对象

         方法区类静态属性引用的对象

         方法区常量引用的对象

         本地方法栈中(native方法)引用的对象

2. 三种垃圾回收算法:标记-清除算法、复制算法以及标记-整理算法

2.1 标记-清除算法,将垃圾标记出来,然后清理掉。清理完的内存区域就变成可使用的了。但是,那些垃圾所在的区域可能间隔的,容易产生内存碎片。不利于后续对象使用。

2.2 复制算法,2.1的演化版本,可有效解决内存碎片的问题,它将内存区域分为等大小的两块,每次只用其中一块。一块用完了,就将还存活的对象依次复制到另一块,同时清理掉已使用的这块,内存连续可用。但是,内存未得到最大话的利用,而且复制成本也高。

2.3 标记-整理算法,不是清除垃圾,而是将存活对象向一端移动,再清理掉端外的内存区域。既没有碎片,也利用了空间,可是对内存变动频繁,整理存活对象的引用地址,效率低丫。

分代收集算法融合了上述三种算法的思想,打出一套组合拳。

3. Java堆分为新生代和老年代(Old),比例是1:2。新生代中,发现大批对象死去,只有少量存活,用复制算法,成本也较低。老年代中对象的存活率比较高,用标记-清除或者标记-整理算法进行回收。

3.1 新生代分为Eden区和Survivor区,比例是8:2。Survivor区又分为From区和To区,比例是1:1。

首先,大部分对象朝生夕死,在Eden区被分配,Eden满了之后,JVM会进行依次Minor GC(比Major频繁且快)。Minor GC后,Eden区被清空,大部分对象被回收,存活的进Survivor的From区(From区满了,直接进Old区)

3.2 Survivor区相当于Eden区和Old区的一个缓冲,为啥需要呢?因为一次Minor GC后就将“漏网之鱼”直接送进Old区,那么Old区很快就会被填满。我们在Survivor区将“残党余孽”剔除干净,再送Old区。Survivor区的意义在于减少被送到老年代的存活对象,进而减少Major GC的发生(需要STW,Stop-The-World,挂起整个应用程序)。只有经历16次Minor GC还存活的对象,才会被送到Old区。

那为啥需要两个呢?即From区和To区。为了解决内存碎片化。如果只有一个区域,会怎样?Eden区满了,存活对象进 Survivor区,而 Survivor区可能本身也有存活对象,那么如何区分呢?标记-清除可以,但是容易产生内存碎片。所以,有一个To区,每次Minor GC,将Eden区和From区的存活对象复制到To区,清空Eden区和From区,下一次Minor GC,再将Eden区和To区的存活对象复制到From区,以此反复。

好处:Survivor区永远有个备胎(空闲着),要么是From区要么是To区,而且非空的无碎片。

3.3 Old区占的内存空间比较大,只有在Major GC时才会清理。内存越大,STW的时间越长),由于复制算法效率在此很低,所以用标记-整理算法。还有一些对象也会进入老年代:

1)大对象:需要大量连续内存空间的对象

2)长期存活对象:JVM给每一个对象一个Age,一般对象在Survivor区的From区和To区移动,当Age=15时,才被送到Old区。也可自行设置改变这个15

3)若Survivor区相同年龄所有对象大小的总和大于Survivor区空间的一半时,Age>=该年龄的对象直接送Old区,无需等你“成年”到15岁。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值