JVM成神之路——垃圾回收详解2

垃圾收集器

垃圾收集算法是内存回收的方法

垃圾收集器就是具体实现这些算法,并实现内存回收

3.5经典垃圾收集器

 

3.5.1Serial收集器

最古⽼的垃圾收集器,⼀款基于新⽣代的收集器,采⽤复制算法。可与CMS和Serial old相配合,

GC线程是单线程,且不与⽤户线程并发,GC期间会暂停所有⽤户线程。

 

3.5.2ParNew收集器

Parnew收集器是Serial收集器的多线程并⾏版本,也为新⽣代收集器,采⽤复制算法。Serial收集器只有

⼀条GC线程,⽽Parnew有多条GC线程收集器。

 

3.5.3Parallel Scavenge收集器

Parallel Scavenge收集器同样是⼀款新⽣代收集器,采⽤复制算法。但它更关注吞吐量,吞吐量=⽤户代码运⾏时间/总时间,相当于⽤户代码所占的⽐重。有-XX:GCTimeRalto来控制吞吐量

3.5.4Serial Old收集器

是Serial收集器的⽼年代版本,采⽤标记-整理算法

 

3.5.5Parallel Old收集器

是Parallel Scavenge收集器的⽼年代版本,采⽤标记-整理算法,⽀持多线程并⾏。当Parallel old出来之后,“吞吐量优先”才有了名副其实的组合搭配。

3.5.6CMS收集器(Concurrent Mark Sweep)

CMS是⼀款优秀的收集器,可以看出是(Mark Sweep)基于标记-清除算法的,⽼年代的收集器。它是第⼀款可以与⽤户线程并发的收集器。它的收集过程主要分为⼀下四个阶段:

  1. 初始标记:找到直接与GCRoots直接关联的对象进⾏标记
  2. 并发标记:这⼀步是要遍历整个对象图,时间相对较⻓,但是可以与⽤户进程并发进⾏
  3. 重新标记:这⼀步是对并发过程中,对象引⽤改变的⼀⼩部分进⾏重新标记
  4. 并发清理:将标记到的已经死亡的对象进⾏回收清理优点:并发收集,低停顿

缺点:1)对内存资源敏感,当然也是不可避免,在并发过程中,⽤户线程会变慢

    1. ⽆法清理浮动垃圾,只能放到下⼀次清理中
    2. 由于标记-清除算法的原因,会产⽣很多不连续的空间碎⽚

3.3.6G1收集器(Garbage First)

G1收集器是⼀次思想上的⾰命性收集器,是基于全堆的收集器,它在思想上仍然保持分代理论,但在内存布局上发⽣了⾰命性的改变,内存布局上没有新⽣代和⽼年代⼀说。把整个Java堆分为若⼲相同⼤⼩的区域(Region)

,每块Region会根据需要扮演相应的新⽣代、⽼年代区域。当回收时,系统会根据⽤户要求的的停顿时间及吞吐量,在后台维护⼀个优先回收集,根据回收之后释放的空间的⼤⼩和回收所需的时间来进⾏排序。优先处理那些回收受益Y⼤的对象,这也是G1名字的由来。还有⼀类特殊的Humongous Region,

⽤来存放⼤对象。G1中将超过⼀般Region的对象成为⼤对象,还有⼀些超级⼤对象被放在连续的⼏块

Region中。

*在Region中,有两个TAMS指针,⽤来分配并发回收期间的新对象,每个并发时期分配的新对象的位置都在这两个指针之上

 

G1的回收过程有以下四个阶段:

  1. 初始标记:只标记与GCRoot's直接关联的对象,改变TAMS指针的值,以便后续在Region可以分配对象
  2. 并发标记:从GCRoots开始遍历整个堆内存的对象图(可达性分析),遍历完之后,在重新遍历在

SATB(原始快照)的记录下引⽤有变动的对象

  1. Y终标记:进⾏在并发结束时,对SATB时的Y后⼀⼩部分引⽤变动的对象进⾏标记(做⼀个短暂停顿)
  2. 筛选回收:将所有要回收的对象,根据⽤户要求的Y⼤停顿时间,来根据回收后的收益⼤⼩进⾏回收。也可以建⽴⼀个回收集,根据回收后的收益⼤⼩进⾏排序回收。(也需要对⽤户线程进⾏停顿)

优点:

  1. 可根据⽤户的需求Y⼤停顿时间来满⾜垃圾回收的时间
  2. 加上回收集,这种回收收益Y⼤化的模式
  3. 创新性的Region布局缺点:

额外的内存资源:在G1收集器中,每个Region都需要有⼀个记忆集,来装载双向的来⾃其他Region的引⽤,不仅是我指向其他,还有其他指向我,都需要存储。这使得G1⽐CMS要多消耗百分之20的内存甚⾄更多。相⽐之下,CMS的记忆集就简单多了,只有⽼年代指向新⽣代的引⽤。

3.6低延迟垃圾收集器

迄今为⽌,所有的垃圾收集器都在为了占⽤内存、吞吐量、延迟这三个因素努⼒,但想要这三者都达到极端⼏乎是不可能的,这三者构成了⼀个“不可能三⻆形”,⽽以往的收集器Y多可以将其中的两个做到较好。但现在,⼈们越来越在延迟⽅⾯的要求⾼了。

3.7选择正确的收集器

3.7.1Epsilon收集器

Epsilon收集器——⼀款不能进⾏垃圾回收功能的收集器。

在⼤环境的影响之下,Java对于⼀些⼩的服务显得有点先天不⾜,如果你的应⽤或服务只运⾏⼏分钟或者数秒,往往没有任何回收能⼒的Epsilon收集器Y适合。

3.7.2收集器的权衡

如果是科学技术应⽤,尽快算出结果⽐较重要,⾸先要关注的就是吞吐量若果是SLA等协议应⽤,延迟是Y⼤关注点如果是客户端或者嵌⼊式应⽤,内存占⽤就是⾸要⽬标

3.7.3虚拟机与垃圾收集器⽇志

格式:【-Xlog:(selector):(output):(decorators):(output-options)】

其中Y重要的就是参数就是选择器Selector,它由标签(Tag)和⽇志级别(Level)共同组成。标签Tag就相当于某个功能块的名字,⽇志级别按详细程度分为六类:Trace,Debug,Info,

Warning,Error,Off

  1. 输出GC基本信息 -Xlog:gc (线程名) 如:-Xlog:gc GCTest
  2. 输出GC详细信息 -Xlog:gc* (线程名)如:-Xlog:gc* GCTest
  3. 输出GC前后的堆、⽅法区的可⽤容量变化-Xlog:gc+heap=debug  (线程名)
  4. 输出GC过程中⽤户线程并发时间和停顿的时间:-Xlog:safepoint  (线程名)
  5. 输出收集器Ergonomics机制⾃动调节的想换信息:-Xlog:gc+ergo*=trace (线程名)【⾃动设置堆空间个各分代区域⼤⼩、收集⽬标】
  6. 输出熬过收集后的对象年龄分布信息:-Xlog:gc+age=trace (线程名)

3.8内存分配与回收策略

  1. 新对象优先分配在Eden区,当Eden区没有可⽤空间进⾏分配的话,将会进⾏⼀次MinorGC
  2. ⼤对象直接分配在⽼年区(超过参数-XX:PretenureSize Thrashold,分配在⽼年区)
  3. ⻓期存活的对象将存活在⽼年代(超过参数:-XX:Tenuring Thrashold进⼊⽼年区,默认为15)
  4. 动态对象年龄判定(当年龄相同的对象所有加起来的⼤⼩超过Survivor区的⼀半,年龄⼤于或等于该年龄的直接进⼊⽼年区)
  5. 5)空间分配担保: 当进⾏Minor时,会检查⽼年代的可⽤空间是否⼤于新⽣代所有对象的总空间,若⼤于则MinorGC是安全的,若不⼤于检查虚拟机是否允许担保失败(默认为允许),-XX:HandlePromotionFailure,若允许,则检查⽼年代的空间是否⼤于历次进⼊⽼年代的对象的平均值,若⼤于则进⾏⼀次MinorGC。若⼩于或者不允许,则改为⼀次Full GC。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值