最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

焦点要闻:读Java性能权威指南(第2版)笔记18_垃圾回收E

来源:博客园

1.回收

1.1.找到不使用的对象

1.2.释放它们的内存

1.3.压缩堆

1.4.合在一起称为回收

2.Throughput回收器

2.1.工作细节比较简单

2.1.1.可以在同一个GC周期内完成回收

2.1.2.在单次操作过程中回收新生代或老年代

2.2.Minor GC

2.2.1.当Eden空间被填满时,新生代回收就会发生

2.2.2.新生代回收会将所有的对象移出Eden空间

  • 2.2.2.1.Eden空间一般是空的

  • 2.2.2.2.不认为它被压缩了


    (资料图片仅供参考)

2.2.3.另一些被移到老年代

2.2.4.还有大量对象因不再使用而被丢弃

2.3.Full GC

2.3.1.老年代回收会将新生代中的所有对象释放出来

2.3.2.只有老年代中还剩下活跃引用的对象

2.3.3.所有这些对象占用的空间都会被压缩

  • 2.3.3.1.只占用老年代的开始部分

  • 2.3.3.2.其余部分是空闲的内存空间

2.4.优化

2.4.1.围绕停顿时间进行的

2.4.2.权衡

  • 2.4.2.1.时间和空间的取舍

    • 2.4.2.1.1.更大的堆会消耗机器上更多的内存

    • 2.4.2.1.2.应用程序会有更高的吞吐量

  • 2.4.2.2.执行GC所需的时间长度

    • 2.4.2.2.1.增加堆的大小可以减少Full GC停顿的次数

    • 2.4.2.2.2.GC时间较长,可能延长平均响应时间

    • 2.4.2.2.3.为了缩短GC停顿时间

    • 2.4.2.2.3.1.将更多的堆分配给新生代而不是老年代

    • 2.4.2.2.3.2.会增加老年代回收的频率

2.5.自适应大小

2.5.1.重新调整堆(和代)的大小,以实现其停顿时间的目标

  • 2.5.1.1.并不总是堆越大就越好

2.5.2.当给定的停顿时间目标不切实际时,应用程序的行为会更糟糕

2.5.3.-XX:MaxGCPauseMillis=N

  • 2.5.3.1.用于设定应用程序可接受的最大停顿毫秒数

  • 2.5.3.2.默认情况下,不设置这个标志

  • 2.5.3.3.适用于Minor GC和Full GC

  • 2.5.3.4.如果使用了一个非常小的值,那么应用程序最终会得到一个非常小的老年代

    • 2.5.3.4.1.导致JVM非常频繁地执行Full GC,应用程序的性能会很糟糕

2.5.4.GC中花费总时间3%到6%的应用程序,运行效果相当好

2.5.5.-XX:GCTimeRatio=N

  • 2.5.5.1.设定你希望应用程序在GC上花费的时间(相对于应用程序线程应该运行的时间)

  • 2.5.5.2.标志的默认设置很适用

    • 2.5.5.2.1.默认值是99

    • 2.5.5.2.2.在没有其他目标的情况下,推荐时间比例设置为19(GC时间占5%)

  • 2.5.5.3.ThroughputGoal=1-(1÷ (1+GCGCTimeRatio))

3.CMS回收器

3.1.已废弃

3.2.3个基本操作

3.2.1.回收新生代(同时暂停所有的应用程序线程)

3.2.2.运行并发周期来清理老年代的数据

3.2.3.如果有必要,执行Full GC来压缩老年代

3.3.对象会从Eden空间移到一个Survivor空间(Survivor空间满了之后就移动到老年代)

3.4.默认情况下,CMS不会回收元空间

3.5.除非发生Full GC,否则永远不会调整新生代的大小

3.6.CMS周期的停顿一般比新生代停顿短得多,特定的应用程序可能对这些额外的停顿并不敏感

3.7.并发周期

3.7.1.初始标记(initial mark)阶段开始

  • 3.7.1.1.会暂停所有应用程序线程

3.7.2.标记(mark)阶段

  • 3.7.2.1.不会暂停应用程序线程

3.7.3.预清理(preclean)阶段

  • 3.7.3.1.和应用程序线程同时运行

3.7.4.重新标记(remark)阶段

  • 3.7.4.1.不是并发的,会暂停所有的应用程序线程

3.7.5.可中止的预清理(abortable preclean)阶段

  • 3.7.5.1.会等到新生代被占用50%后才开始

  • 3.7.5.2.阶段的中止,这是停止这个阶段的唯一方式

3.7.6.清除(sweep)阶段

3.7.7.并发重置(reset)阶段

  • 3.7.7.1.最后一个阶段

3.8.当发生新生代回收,但是老年代中并没有足够的空间容纳预计要晋升的对象时,CMS会执行Full GC

3.8.1.所有的应用程序线程都会被暂停

3.8.2.该操作是单线程的

  • 3.8.2.1.它耗时如此之长的原因之一

  • 3.8.2.2.并发模式失败随着堆的增长而影响更大的原因之一

3.8.3.这种并发模式失败是CMS被废弃的主要原因

3.9.老年代中有足够的空间容纳晋升对象,但空闲空间是碎片化的,所以对象晋升还是会失败

3.9.1.CMS无法晋升对象,因为老年代是碎片化的

3.9.2.要晋升的内存量比CMS预期的要大,这种情况更少

3.10.CMS的日志可能显示了Full GC,但是没有任何常规的并发GC消息

3.10.1.当元空间被填满并需要回收时,这种情况就会发生

3.10.2.CMS不会回收元空间,所以如果它被填满了,就需要Full GC来丢弃任何未被引用的类

3.11.优化

3.11.1.确保不会发生并发模式失败或晋升失败

  • 3.11.1.1.避免并发模式失败是实现CMS最佳性能的关键

  • 3.11.1.2.避免这些失败的最简单的方法(在可能的情况下)是增加堆的大小

3.11.2.当执行新生代回收时,CMS计算出没有足够的空间容纳这些将晋升到老年代的对象,所以会先回收老年代

3.11.3.让老年代空间更大一些,要么调整新生代和老年代的比例,要么增加更多的堆空间

3.11.4.更频繁地运行后台线程

  • 3.11.4.1.提早开始并发周期

  • 3.11.4.2.-XX:CMSInitiatingOccupancyFraction=N

    • 3.11.4.2.1.默认为70

    3.11.4.2.1.1.CMS并发周期会在老年代被占用70%时开始

    • 3.11.4.2.2.不要将该值设置得低于堆中的活跃数据量,至少应加上10%到20%
  • 3.11.4.3.-XX:+UseCMSInitiatingOccupancyOnly

    • 3.11.4.3.1.默认情况下false
  • 3.11.4.4.如果两个都设置了,CMS就会只根据老年代的填充比例来决定何时启动后台线程

  • 3.11.4.5.此处的占用率是基于老年代的,而不是整个堆

3.11.5.使用更多的后台线程

  • 3.11.5.1.-XX:ConcGCThreads=N

    • 3.11.5.1.1.增加后台线程数量

    • 3.11.5.1.2.ConcGCThreads = (3 + ParallelGCThreads) / 4

    • 3.11.5.1.3.能比G1 GC早一步增加ConcGCThreads的值

3.12.MaxGCPauseMllis=N

3.12.1.见前文

3.13.GCTimeRatio=N

3.13.1.见前文

关键词: