JVM_05 垃圾回收制(GC调优)
JVM 调优 垃圾 05 回收 GC
2023-09-11 14:17:55 时间
GC 调优
预备知识:
- GC相关的VM参数:官方文档
- 查看虚拟机参数命令:
"C:\Program Files\Java\jdk1.8.0_201\bin\java" -XX:+PrintFlagsFinal -version | findstr "GC"
D:\Note\笔记\JDK源码学习\IDEA-workspace\jdk8>"C:\Program Files\Java\jdk1.8.0_201\bin\java" -XX:+PrintFlagsFinal -version | findstr "GC"
uintx AdaptiveSizeMajorGCDecayTimeScale = 10 {product}
uintx AutoGCSelectPauseMillis = 5000 {product}
bool BindGCTaskThreadsToCPUs = false {product}
uintx CMSFullGCsBeforeCompaction = 0 {product}
uintx ConcGCThreads = 0 {product}
bool DisableExplicitGC = false {product}
bool ExplicitGCInvokesConcurrent = false {product}
bool ExplicitGCInvokesConcurrentAndUnloadsClasses = false {product}
uintx G1MixedGCCountTarget = 8 {product}
uintx GCDrainStackTargetSize = 64 {product}
uintx GCHeapFreeLimit = 2 {product}
uintx GCLockerEdenExpansionPercent = 5 {product}
bool GCLockerInvokesConcurrent = false {product}
uintx GCLogFileSize = 8192 {product}
uintx GCPauseIntervalMillis = 0 {product}
uintx GCTaskTimeStampEntries = 200 {product}
uintx GCTimeLimit = 98 {product}
uintx GCTimeRatio = 99 {product}
bool HeapDumpAfterFullGC = false {manageable}
bool HeapDumpBeforeFullGC = false {manageable}
uintx HeapSizePerGCThread = 87241520 {product}
uintx MaxGCMinorPauseMillis = 4294967295 {product}
uintx MaxGCPauseMillis = 4294967295 {product}
uintx NumberOfGCLogFiles = 0 {product}
intx ParGCArrayScanChunk = 50 {product}
uintx ParGCDesiredObjsFromOverflowList = 20 {product}
bool ParGCTrimOverflow = true {product}
bool ParGCUseLocalOverflow = false {product}
uintx ParallelGCBufferWastePct = 10 {product}
uintx ParallelGCThreads = 8 {product}
bool ParallelGCVerbose = false {product}
bool PrintClassHistogramAfterFullGC = false {manageable}
bool PrintClassHistogramBeforeFullGC = false {manageable}
bool PrintGC = false {manageable}
bool PrintGCApplicationConcurrentTime = false {product}
bool PrintGCApplicationStoppedTime = false {product}
bool PrintGCCause = true {product}
bool PrintGCDateStamps = false {manageable}
bool PrintGCDetails = false {manageable}
bool PrintGCID = false {manageable}
bool PrintGCTaskTimeStamps = false {product}
bool PrintGCTimeStamps = false {manageable}
bool PrintHeapAtGC = false {product rw}
bool PrintHeapAtGCExtended = false {product rw}
bool PrintJNIGCStalls = false {product}
bool PrintParallelOldGCPhaseTimes = false {product}
bool PrintReferenceGC = false {product}
bool ScavengeBeforeFullGC = true {product}
bool TraceDynamicGCThreads = false {product}
bool TraceParallelOldGCTasks = false {product}
bool UseAdaptiveGCBoundary = false {product}
bool UseAdaptiveSizeDecayMajorGCCost = true {product}
bool UseAdaptiveSizePolicyWithSystemGC = false {product}
bool UseAutoGCSelectPolicy = false {product}
bool UseConcMarkSweepGC = false {product}
bool UseDynamicNumberOfGCThreads = false {product}
bool UseG1GC = false {product}
bool UseGCLogFileRotation = false {product}
bool UseGCOverheadLimit = true {product}
bool UseGCTaskAffinity = false {product}
bool UseMaximumCompactionOnSystemGC = true {product}
bool UseParNewGC = false {product}
bool UseParallelGC := true {product}
bool UseParallelOldGC = true {product}
java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)
bool UseSerialGC = false {product}
- 可以根据参数去查询具体的信息:
1. 调优领域
- 内存
- 锁竞争
- CPU占用
- IO
- GC
2. 确定目标
低延迟/高吞吐量? 选择合适的GC
- CMS G1 ZGC
- ParallelGC
- Zing
3. 最快的GC是不发生GC
首先排除减少因为自身编写的代码而引发的内存问题:
- 查看Full GC前后的内存占用,考虑以下几个问题:
- 数据是不是太多?
resultSet = statement.executeQuery("select * from 大表");
- 数据表示是否太臃肿?
- 对象图
- 对象大小,Java中new一个Object或者包装类型对象,至少16字节。
- 是否存在内存泄漏?
static Map map = HashMap()
,当我们不断的向静态的map中新增对象且不移除,就可能造成内存吃紧。- 可以使用软引用,弱引用来解决上面的问题,因为它们可以在内存吃紧时,被定期回收。也可以使用第三方的缓存中间件来存储上面的map中的数据。
- 数据是不是太多?
4. 新生代调优
- 新生代的特点:
- 当我们
new
一个对象时,会先在伊甸园中进行分配,所有的new
操作分配内存都是非常廉价且速度极快的- TLAB(Thread-Location Allocation Buffer):当我们
new
一个对象时,会先检查TLAB缓冲区中是否有可用内存,如果有则优先在TLAB中进行对象分配。
- TLAB(Thread-Location Allocation Buffer):当我们
- 死亡对象回收的代价为零
- 大部分对象用过即死(朝生夕死)
- MInor GC 所用时间远小于Full GC
- 当我们
- 新生代内存越大越好么?
- 不是:
- 新生代内存太小:频繁触发Minor GC,会 STW,会使得吞吐量下降。
- 新生代内存太大:老年代内存占比有所降低,会更频繁地触发Full GC。而且触发Minor GC时,清理新生代所花费的时间会更长。
- 新生代内存设置为能容纳
并发量*(请求-响应)
的数据为宜。
- 不是:
5. 幸存区调优
- 幸存区最大能够保存 当前活跃对象+需要晋升的对象。
- 晋升阈值配置得当,让长时间存活的对象尽快晋升。
6. 老年代调优
以CMS为例:
- CMS的老年代内存越大越好。
- 先尝试不做调优,如果没有 Full GC 那么说明当前系统暂时不需要优化,否则,就先尝试调优新生代。
- 观察发生Full GC 时老年代的内存占用,将老年代内存预设调大
1/4 ~ 1/3
。-XX:CMSInitiatingOccupancyFraction=percent
7. 案例
- 当Full GC 和 Minor GC 调用频繁。
- 当请求高峰期发生Full GC,单次暂停时间特别长(CMS)
- 在老年代充裕的情况下,发生Full GC (1.7)
上面集中情况都是需要调优的!
相关文章
- JVM性能优化, Part 5:Java的伸缩性
- jvm参数调优
- Unrecognized Windows Sockets error: 0: JVM_Bind 异常解决办法
- JVM调优的正确姿势
- JVM常用调优案例
- JVM类加载器
- JVM 第二篇:垃圾收集器以及算法
- JVM调优总结(一)- 一些概念
- JVM源码分析之JDK8下的僵尸(无法回收)类加载器
- jvm的生命周期:启动、执行、退出
- JVM调优:CMS的执行过程及存在的问题
- JVM调优:一个对象从出生到消亡过程
- JVM调优:常见垃圾回收算法
- JVM调优:定位垃圾的常用算法
- jvm调优:何为垃圾及与c++的对比
- JVM 垃圾收集器CMS相关参数
- JVM 调优实战--什么是调优及如何调优的思路
- JVM 调优实战--垃圾收集器(串行、ParNew并行、ParallelNew并行、CMS、G1)
- JVM 调优实战--垃圾回收的常见算法
- 【JVM与性能调优】Java虚拟机发展史与Sun HotSpot VM入门介绍
- 【JVM】JVM 性能调优监控工具 jps、jstack、jmap、jhat、jstat、hprof 使用详解
- n-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter convertView
- 【jvm优化】线上JVM调优实践
- 【jvm优化超详细】常见的JVM调优场景
- JVM调优概述
- JVM GC原理及调优的基本思路
- HotSpot JVM 内存管理