读Java性能权威指南(第2版)笔记15_垃圾回收B

1. GC触发条件

1.1. 当新生代满的时候

1.1.1. Minor GC会被触发

1.2. 当老年代满的时候

1.2.1. Full GC会被触发

1.3. 当堆快要填满时

1.3.1. 并发GC(如果适用)会被触发

2. 强制开启GC

2.1. System.gc()方法

2.1.1. 总是会触发Full GC(即使JVM运行的是G1GC或者CMS)

2.1.2. 并不会让应用程序更高效

2.1.2.1. 只是让GC比其他情况更早开启,也只是将性能的影响延迟了

2.1.3. 调用这个方法从来都不是好主意

2.2. 例外

2.2.1. 在做性能监控或基准测试时

2.2.1.1. 对于运行少量代码的小型基准测试,为了加快预热JVM,在测量期之前强制执行GC有意义

2.2.2. 对堆进行分析时,在堆转储之前强制触发Full GC是个好主意

2.2.3. 远程方法调用

2.2.3.1. Remote Method Invocation,RMI

2.2.3.2. 作为分布式垃圾回收器的一部分,它每小时调用一次System.gc()方法

2.2.3.3. -Dsun.rmi.dgc.server.gcInterval=N

2.2.3.4. -Dsun.rmi.dgc.client.gcInterval=N

2.2.3.5. N以毫秒为单位

2.2.3.6. 默认值是3 600 000(1小时)

2.3. -XX:+DisableExplicitGC

2.3.1. 阻止强制GC操作

2.3.2. 默认false

3. CPU使用率

3.1. 要确保CPU告警不是由Full GC引起的100%CPU使用率造成的

3.2. 也不是由后台并发处理线程引起的CPU高峰持续时间更长(但使用率更低)造成的

3.3. Java应用程序来说是很正常的

4. 选择GC算法

4.1. 在JDK 8中,要如何选择则取决于你的应用程序

4.2. 在单CPU的机器上默认使用Serial垃圾回收器

4.2.1. 包括单个CPU的虚拟机和限制只能使用一个CPU的Docker容器

4.3. 当在单CPU机器上运行CPU密集型应用程序时,即使这个CPU是超线程的,使用Serial垃圾回收器也更有意义

4.4. 如果平均响应时间是最重要的目标,Serial垃圾回收器是更好的选择

4.5. 在批处理任务中,CPU会在很长一段时间内100%忙碌,Serial垃圾回收器有明显的优势

4.6. 堆很小(比如100 MB)的应用程序,无论可用的核心数量是多少,使用Serial垃圾回收器可能都会有更好的表现

4.7. 如果一个长期运行的应用程序线程占用了唯一可用的CPU,那么G1 GC不是一个好的选择

4.8. 在JDK 11中,G1 GC通常是更好的选择

4.9. 对于大多数应用程序来说,G1 GC的算法是更好的选择

4.10. 如果你想优化第99百分位响应时间,那么G1 GC更好

4.11. 在同样的硬件上处理非CPU密集型任务,G1GC是更好的选择

4.12. 当你选择G1 GC时,需要有足够的CPU供后台线程运行

4.13. 在CPU周期足够的情况下,即使Serial垃圾回收器是默认的选择,G1 GC一般也会表现得更好

4.14. 如果服务器缺少CPU周期,会导致G1 GC和应用程序线程竞争CPU,那么G1 GC的响应时间会更长

4.15. 如果更看重交互处理和响应时间,那么Throughput垃圾回收器很难战胜G1 GC

4.16. 如果优化服务器之后没有了Full GC,那么G1 GC和Throughput垃圾回收器通常会得到相似的结果

4.16.1. Throughput垃圾回收器遇到的Full GC越多,G1 GC的平均响应时间、第90百分位响应时间和第99百分位响应时间就会越短

4.17. 当应用程序的运行时间是关键时,如果Throughput垃圾回收器的应用程序线程停顿时间比G1 GC少,那么它就更有优势

4.17.1. 没有(或很少)Full GC。

4.17.2. 老年代常常是满的,G1 GC后台线程有更多工作要做

4.17.3. G1 GC线程亟需CPU周期

4.18. 在多CPU机器上运行CPU密集型任务时,Throughput垃圾回收器更有意义

4.19. 即使任务不是CPU密集型的,如果它产生的Full GC相对较少或者老年代一般是满的,Throughput垃圾回收器也可能是更好的选择