深入理解jvm虚拟机第三章总结

1如何判断垃圾

  判断一个对象是否是垃圾就看这个对象是否还被引用,如果这个对象还被引用,就说明有用到的可能,没被引用就说明之后不可能被使用,就是垃圾。判断方法有两种

1.引用计数法

   就是一个对象被引用一次就++一次;但是会存在两个对象相互引用,最终成环。

2可达性分析

  就是从GC Roots出发,能够达到的对象就是被引用的的对象,不能到达的对象就说明在线程执行过程不可能被调用,视为垃圾。

  在java中被标记为是垃圾还不会马上被GC,会依照条件执行对象的finalize方法,条件是对象重写过finalize()方法或者这个方法已经被执行过了,书中推荐忘记这个方法,能够严重被回收可以是一个类中含有一个类型是类本身的静态变量,在执行finalize方法的时候将自身赋给这个变量。(除了这种操作我也想不到怎么让对象还能被引用)

  java中对于对象还有分4中引用方式具体查看java4中引用

方法区的回收

 

2基本的垃圾收集算法

  1.标记清除算法

      标记清楚算法就是先找出垃圾,然后标记那块内存为空,通常要搭配free list使用,配合空闲列表的分配空间方法。缺点是会出现不连续的内存碎片。

 2.标记整理算法

    标记真理是找出垃圾后,将未删除的垃圾往前移,类似在数组中找出需要删除的元素,将未删除的元素前往移动。

  3.复制算法

   需要两块空间进行操作,总有一块空间为空白,在垃圾回收时将垃圾标记,之后将不是垃圾的对象复制到另外一块中。缺点是需要一块额外的空间

 4.分代算法

  根据对象中的存活时间来采取垃圾回收算法,对于存活时间较短的对象放在yong区,存活长的时间放在old区。

HotSpot 算法细节实现

1枚举根节点,对于虚拟机如何实现GC,关于OomMap的理解 

2 安全点和安全区域 在执行GC算法的时候,需要线程处于安全点的状态,才能去执行GC操作。

让线程处于安全点有两种方式,一种是抢先式中断,就是需要GC的时候直接全部中断线程,去检查线程是否处于安全点的状态,如果没处于就将线程跑到安全点,这种方式很少被采取,大部分采取的是主动式中断,通过设置一个标志,在线程每次到达安全点的时候,去询问是否需要GC,需要就进行中断等待GC。如果有些线程被阻塞了,不能走到安全点去,那么会被放在安全区域,在安全区域中的线程的对象引用关系不会改变。

各种垃圾收集器

图片中有连线的就是说明垃圾收集器能够搭配使用,其实我觉得明白了图片上每条连线的含义,和有些算法间为啥没有连线,就算理解了大部分垃圾收集器。

1.serial 和serial old 垃圾收集器

  单线程的垃圾收集器,在线程执行全过程都是STW,如果运行在单核CPU上,效果非常好,但是如果运行在多核cpu上,相当于在垃圾回收的时候,设备只有一个CPU,这个收集器简单高效,因为没有申请其他线程等额外的线程开销,因为单线程的影响,serial放在客户端(app,电脑软件等)比较好用,不适合服务端。具体运行方式看下图

 

2.ParNew

  同样是yong区的收集器相比于serial,ParNew只是一个多线程版本的serial,在线程执行全过程都还是是STW,因为上文说到的,在多个cpu的时候,serial不能很好的利用到多核cpu的资源,从而有了parnew,但是在双核的情况下,parnew的效率不一定比serial高,因为parnew是多线程的,就要申请线程资源等一系列费时的操作(所以为什么说serial效率高,因为单线程),但是在cpu较多的情况下,parnew效率比serial高

 

3CMS(concurrent  mark  sweep)

  cms是一个作用域old区的垃圾收集器,是一款注重于停顿时间的垃圾收集器,从名字上可以看出,基于标记清除算法的,cms在垃圾回收阶段有4个过程,

 

 初始标记(STW initial mark)

在这个阶段,需要虚拟机停顿正在执行的应用线程,官方的叫法STW(Stop Tow World)。这个过程从根对象扫描直接关联的对象,并作标记。这个过程会很快的完成。

· 并发标记(Concurrent marking)

这个阶段紧随初始标记阶段,在“初始标记”的基础上继续向下追溯标记。注意这里是并发标记,表示用户线程可以和GC线程一起并发执行,这个阶段不会暂停用户的线程哦。

· 重新标记(STW remark)

这个阶段会再次暂停正在执行的应用线程,修正并发阶段因为用户程序导致标记产生变动的那一部分对象的标记记录,进行这一次耗时会比“初始标记”更长,并且这个阶段可以并行标记。

· 并发清理(Concurrent sweeping)

这个阶段是并发的,应用线程和GC清除线程可以一起并发执行。

CMS有很多优点,但是CMS有以下三个缺点,

1.对于cpu资源十分敏感当CPU核数较少的时候,会对cpu产生很大的压力,影响用户线程。

2.因为在执行玩初始标记之后,GC线程和用户线程共同完成,用户线程此时也会产生垃圾,这些垃圾称作浮动垃圾,这些垃圾不能再这次GC总被回收,要等到下次GC,所以要预留出一部分的空间的时候就要等待GC。可以通过设置参数CMSInitiatingOccupancyFraction来设置当老年代使用%多少的时候执行CMS算法,官网建议68%,如果在一次CMS的GC中发现了old区不够用的情况下就不能让CMS和用户线程并发执行了,这时候使用serial old收集器,进行垃圾回收,这就是为什么上面图中serial old 和cms同为old区的收集器,但是能有条连线的原因。

3.因为cms采用的是标记清除算法,所以必然会有空间碎片的问题,old区域没有达到需要cms进行GC的阈值,但是对象来了无法进行内存分配,这个时候就需要调用full gc,给内存带来很大的压力,可以通过设置 CMSFullGCsBeforeCompaction 参数来设置在执行CMS却没执行FULL 的时候,将内存进行压缩。

4 paralle和parall old

  parallel是一个注重吞吐量的收集器,在执行过程都是STW的并行执行,提供了设置最大垃圾收集花费数据和吞吐量大小的参数,但是parrallel不建议设置手工指定新生代大小,晋升老年代的阈值等细节参数,parallel会适应当前的虚拟机情况,进行调整,但是最大垃圾收集花费数据和吞吐量大小的参数也不能随便设置,那样会引起频繁的垃圾回收。除去以上的特点,parrallel和parnew没多大大差别。

说一下为什么parallel不能cms共同配合的原因,因为cms是需要预留空间才进行GC的,注重的是用户等待时间,parallel注重的是吞吐量,个人理解来说parallel使用起来什么参数都不用设置,直接等到yong满了在进行GC,那样吞吐量最高,切合初衷,因为这两个收集器的出发点不同,就导致了他们呢不能一起使用,举个例子,98秒的用户线程使用,2秒的垃圾回收,和48.9秒的用户线程使用,1.1秒的垃圾回收,对于cms来说执行结果更切合后一种情况,对面parallel来说执行结果更切合后者。

5.G1收集器

    G1收集器是面向old和yong的一款标记整理收集器

//写了好多,明天再写吧。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值