jvm垃圾回收

1.如何判断对象是垃圾?

1.1 引用计数法

给每个对象加一个计数器,对象被引用则计数器+1。当对象的计数器不为0时,该对象就可以被看作垃圾,等待回收。

缺点:循环引用:A引用了B,B引用了A。

这个方法在主流虚拟机里未被使用。

1.2 可达性分析算法

我们可以将对象之间的互相引用看作一个有向图。从几个起点(被称作GC Roots)开始搜索,就知道哪些对象是被引用了,那么另外那部分没被引用的对象就可以被视为垃圾,等待回收。

GC Roots主要有以下几种:

1.被栈上引用的对象。比如局部变量

2.被类的静态变量(方法区)引用的对象

3.被类的常量(方法区)引用的对象

4.synchronized锁住的对象

等等。。。。

2.垃圾回收算法

第一章介绍了如何判断对象是垃圾。在这个基础上,我们就可以谈谈垃圾回收算法了。常见的GC算法如下:

2.1 标记——清除(mark-sweep)

步骤如下:

标记

根据GCRoots算法,标记哪些对象不是垃圾。

清除

清掉未被标记的对象。

-------------------------------

优缺点分析

优点:

原地回收,不用拷贝、移动对象,所以延迟低。

这样当该区域存活对象比较多的时候,就很适合用这种方法GC。因为拷贝对象的代价更大。那你一定想到了,老年代就很适合这种算法去GC。

缺点:

1.因为清除后没有整理空间,所以会造成空间碎片。容易引起FULL GC,FULL GC是会去整理、移动对象的。这样进程就会停顿(可以简称为STW),更可怕的是,STW的时间是未知的!

2.效率不稳定,与存活对象数量有关。

CMS垃圾收集器的老年代就是用的这种算法。

----------------------------

2.2 标记——复制(mark-copy)

步骤如下:

标记

根据GCRoots算法,标记哪些对象不是垃圾。

复制

将存活对象移动到另一块空余的空间,然后清除其他空间。是的,这种方法会占用多余的空间。

-------------------------------

优缺点分析

优点:

1.没有内存碎片的。比较适合存活对象较少的区域(年轻代)

缺点:

1.移动对象是耗时间的,而且需要停止进程的活动(STW)

2.需要额外消耗空间。

经典的Appel式回收将空间分为Eden区和Servivor区(两块相同大小,假设为Servivor1和Servivor2)。

对象首先在Eden区被创建(如果可以的话),GC时,将Eden区和Servivor1区的存活对象都移动到Servivor2区。然后清除Eden区和Servivor1区。

Servivor1区和Servivor2区是轮流存放存活对象的,下一次GC就是将Eden区和Servivor2区的对象都移动到Servivor1区了。

如果一块Servivor区放不下当次GC的存活对象怎么办?

部分对象可以丢到老年代去。当然老年代也不一定放得下。

2.3 标记——整理算法(mark-compact)

在标记-复制算法中,我们用到了额外空间。

那么可不可以不用额外空间呢?当然是可以的。本方法就是。

它与复制算法的区别就在于,他是在原空间里,把所有存活对象都移动到一端,接着清除另一端的数据。

那么你肯定想知道,为什么年轻代用复制算法而不用整理算法呢?

其实我不知道,因为书上没讲。

书上只说了:年轻代用复制算法,老年代用整理算法。

后面我又翻了别的资料,找到了这样一句话:说明复制算法还是快一点。

好吧,看来水很深我把握不住。有时间再去深入研究下。

-------------------------------

优缺点分析

优点:

1.内存无碎片。也不需要额外空间。

2.总的来说,提高了吞吐量,即:虽然浪费了时间去STW,但无碎片的内存空间使得内存的分配与访问更轻松。总的来说利大于弊。

缺点:

1.移动对象是耗时间的,而且需要停止进程的活动(STW),而且因为老年代存活数量多,STW时间会很长。

2.需要额外消耗空间。

那么这算法有人用吗?有的,G1收集器从整体上看就是这种思想,只是G1以更小的粒度进行回收,使得整理阶段时间短一点。

3.常见垃圾收集器

程序=算法+数据结构

垃圾收集器=GC算法+数据结构。

只介绍两种典型哈,面试吹吹水就行了,多了咱也记不住。

3.1 CMS(Concurrent Mark Sweep) 收集器

特点
名字里带Sweep,显然是基于标记-清除算法的。该算法在清除阶段是不用STW的,很快!
当然,会造成内存碎片,碎片太多就会导致大对象放不下。引起Full GC进行内存整理,而Full GC需要STW,更可怕的是这个STW时间是未知的,这就很危险了。

回收步骤

1.标记GCRoots可达的第一层对象,需要STW,但很快。

2.并发标记:不用STW,很耗时。

3.因为上一步没有STW,所以肯定会有数据不一致,如何处理数据不一致呢?CMS算法中使用了增量更新(反正我没看懂,有时间回来填坑)。

这一步也是SWT的,但也比较快。

4.并发清除

因为就地清除,不涉及到移动活对象,不用STW。清除算法快就快在这个地方!

3.2 G1(Garbage First)收集器

特点

CMS如今已不被看好,G1会变成他的替代者。

我们刚刚有提到,CMS可能会出现GC时间过长的情况,G1解决了这个问题。

我们指定一个最长回收时间,G1就能够算出哪些区域(region,G1将空间划分为一个个region,每个region可以是年轻代、老年代)可以被回收。

G1回收速度不如CMS,但是其系统吞吐量会更高(内存分配与访问的角度)。同时其回收时间可控,这是最关键的。

回收步骤

1.基本上同CMS。不同的是,每个region会单独划分出一块区域给新对象分配。

2.基本上同CMS很耗时。与CMS不同的是,G1采用了SATB方法保证并发执行。

3.基本上同CMS,只不过是处理STAB数据。

4.回收。需要将存活的Region移动到空的Region,比较耗时了。

-------------

哎,这些资料都写的不详细,要不是为了面试我才不看呢。

本文参考资料:《深入理解java虚拟机》第三版

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值