JVM调优

简介: JVM调优

能够进行JVM调优的前提是对JVM的内存结构和GC机制有非常清楚的前提下,以下分别从JVM调优的思路到常见策略两个方面展开说明。

一、JVM调优思路

1.调优目标

  1. 降低系统资源使用率,主要包括CPU和内存(cpu和内存的占用率<=70%,极端情况不能超过90%)
  2. 提升系统吞吐量和响应速度;
  3. 缩短GC时间和频次(GC时间<1s,Full GC尽量不要发生)

2.调优步骤

  1. 分析GC日志和dump日志,判断系统性能瓶颈和可优化点;
  2. 确定优化目标,一般情况资源占用率、系统吞吐量、GC时间很难同时满足优化条件,优先满足主要指标;
  3. 确定优化方向和优化参数,常见是从JVM堆栈参数和GC参数入手;
  4. 调整参数后再进行测试,得出优化前后性能变化,找到最适合的参数;

3.JVM堆栈主要调整参数

  1. -Xms:设置堆的最小空间大小。
  2. -Xmx:设置堆的最大空间大小。
  3. -XX:NewSize:设置新生代最小空间大小。
  4. -XX:MaxNewSize:设置新生代最大空间大小。
  5. -XX:PermSize:设置永久代最小空间大小。
  6. -XX:MaxPermSize:设置永久代最大空间大小。
  7. -Xss:设置每个线程的堆栈大小。

4.主要查看性能工具

  • Jps:java线程查看工具

常用命令有:jps -l -m -v,能够输出main类或jar的全限定名,输出传入main方法的参数,输出传入jvm的参数;

  • Jstack:java线程栈的查看工具

常用命令有:jstack [pid]|grep [tid,同个这种方式可以查询特定线程tid的栈信息;

  • Jmap:java中堆的查看工具

可以通过jmap -dump:format=b,file=[xxx.hprof] [pid]的命令去dump堆类信息

  • jstat:java内置的资源和性能监控工具

可以通过:jstat -gc -h 20 [pid] [interval] 来查询gc信息,其中interval是打印间隔

  • Jinfo:实时查看和调整jvm参数

二、常用的调优策略

1.选择合适的GC垃圾回收器

  1. CPU单核,那么毫无疑问Serial 垃圾收集器是你唯一的选择。
  2. CPU多核,关注吞吐量 ,那么选择PS+PO组合。
  3. CPU多核,关注用户停顿时间,JDK版本1.6或者1.7,那么选择CMS。
  4. CPU多核,关注用户停顿时间,JDK1.8及以上,JVM可用内存6G以上,那么选择G1。

参数配置:

//设置Serial垃圾收集器(新生代)
 开启:-XX:+UseSerialGC
 //设置PS+PO,新生代使用功能Parallel Scavenge 老年代将会使用Parallel Old收集器
 开启 -XX:+UseParallelOldGC
 //CMS垃圾收集器(老年代)
 开启 -XX:+UseConcMarkSweepGC
 //设置G1垃圾收集器
 开启 -XX:+UseG1GC

2.调整JVM堆栈大小

现象:垃圾收集频率非常频繁。

原因:如果内存太小,就会导致频繁的需要进行垃圾收集才能释放出足够的空间来创建新的对象,所以增加堆内存大小的效果是非常显而易见的。

注意:如果垃圾收集次数非常频繁,但是每次能回收的对象非常少,那么这个时候并非内存太小,而可能是内存泄露导致对象无法回收,从而造成频繁GC。

//设置堆初始值
 指令1:-Xms2g
 指令2:-XX:InitialHeapSize=2048m
 //设置堆区最大值
 指令1: -Xmx2g 
 指令2: -XX:MaxHeapSize=2048m
 //新生代内存配置
 指令1:-Xmn512m
 指令2:-XX:MaxNewSize=512m

3.调整内存区域大小比率

现象:某一个区域的GC频繁,其他都正常。

原因:如果对应区域空间不足,导致需要频繁GC来释放空间,在JVM堆内存无法增加的情况下,可以调整对应区域的大小比率。

注意:也许并非空间不足,而是因为内存泄造成内存无法回收。从而导致GC频繁。

参数配置:

//survivor区和Eden区大小比率
 指令:-XX:SurvivorRatio=6  //S区和Eden区占新生代比率为1:6,两个S区2:6
 //新生代和老年代的占比
 -XX:NewRatio=4  //表示新生代:老年代 = 1:4 即老年代占整个堆的4/5;默认值=2

4.设置符合预期的停顿时间

现象:程序间接性的卡顿

原因:如果没有确切的停顿时间设定,垃圾收集器以吞吐量为主,那么垃圾收集时间就会不稳定。

注意:不要设置不切实际的停顿时间,单次时间越短也意味着需要更多的GC次数才能回收完原有数量的垃圾.

参数配置:

//GC停顿时间,垃圾收集器会尝试用各种手段达到这个时间
 -XX:MaxGCPauseMillis 

5.调整对象升老年代的年龄

现象:老年代频繁GC,每次回收的对象很多。

原因:如果升代年龄小,新生代的对象很快就进入老年代了,导致老年代对象变多,而这些对象其实在随后的很短时间内就可以回收,这时候可以调整对象的升级代年龄,让对象不那么容易进入老年代解决老年代空间不足频繁GC问题。

注意:增加了年龄之后,这些对象在新生代的时间会变长可能导致新生代的GC频率增加,并且频繁复制这些对象新生的GC时间也可能变长。

配置参数:

//进入老年代最小的GC年龄,年轻代对象转换为老年代对象最小年龄值,默认值7
 -XX:InitialTenuringThreshol=7 

6.调整大对象的标准

现象:老年代频繁GC,每次回收的对象很多,而且单个对象的体积都比较大。

原因:如果大量的大对象直接分配到老年代,导致老年代容易被填满而造成频繁GC,可设置对象直接进入老年代的标准。

注意:这些大对象进入新生代后可能会使新生代的GC频率和时间增加。

配置参数:

//新生代可容纳的最大对象,大于则直接会分配到老年代,0代表没有限制。
  -XX:PretenureSizeThreshold=1000000 

7.调整 JVM本地内存大小

现象:GC的次数、时间和回收的对象都正常,堆内存空间充足,但是报OOM

原因: JVM除了堆内存之外还有一块堆外内存,这片内存也叫本地内存,可是这块内存区域不足了并不会主动触发GC,只有在堆内存区域触发的时候顺带会把本地内存回收了,而一旦本地内存分配不足就会直接报OOM异常。

注意: 本地内存异常的时候除了上面的现象之外,异常信息可能是OutOfMemoryError:Direct buffer memory。 解决方式除了调整本地内存大小之外,也可以在出现此异常时进行捕获,手动触发GC(System.gc())。

配置参数:

XX:MaxDirectMemorySize

参考资料

  1. 调试排错 - Java 问题排查之Linux命令:https://www.pdai.tech/md/java/jvm/java-jvm-debug-tools-linux.html#文本操作
  2. 【JVM进阶之路】十:JVM调优总结:https://zhuanlan.zhihu.com/p/363961261


目录
相关文章
|
2月前
|
Arthas 监控 Java
(十一)JVM成神路之性能调优篇:GC调优、Arthas工具详解及各场景下线上最佳配置推荐
“在当前的互联网开发模式下,系统访问量日涨、并发暴增、线上瓶颈等各种性能问题纷涌而至,性能优化成为了现时代开发过程中炙手可热的名词,无论是在开发、面试过程中,性能优化都是一个常谈常新的话题”。
162 3
|
2月前
|
监控 Java 测试技术
JVM 性能调优 及 为什么要减少 Full GC
JVM 性能调优 及 为什么要减少 Full GC
85 4
|
3月前
|
监控 Java 调度
探秘Java虚拟机(JVM)性能调优:技术要点与实战策略
【6月更文挑战第30天】**探索JVM性能调优:**关注堆内存配置(Xms, Xmx, XX:NewRatio, XX:SurvivorRatio),选择适合的垃圾收集器(如Parallel, CMS, G1),利用jstat, jmap等工具诊断,解决Full GC问题,实战中结合MAT分析内存泄露。调优是平衡内存占用、延迟和吞吐量的艺术,借助VisualVM等工具提升系统在高负载下的稳定性与效率。
79 1
|
3月前
|
监控 Java 测试技术
Java中的JVM调优技巧
Java中的JVM调优技巧
|
2月前
|
运维 Java Linux
(九)JVM成神路之性能调优、GC调试、各内存区、Linux参数大全及实用小技巧
本章节主要用于补齐之前GC篇章以及JVM运行时数据区的一些JVM参数,更多的作用也可以看作是JVM的参数列表大全。对于开发者而言,能够控制JVM的部分也就只有启动参数了,同时,对于JVM的性能调优而言,JVM的参数也是基础。
|
2月前
|
缓存 监控 Java
Java虚拟机(JVM)性能调优实战指南
在追求软件开发卓越的征途中,Java虚拟机(JVM)性能调优是一个不可或缺的环节。本文将通过具体的数据和案例,深入探讨JVM性能调优的理论基础与实践技巧,旨在为广大Java开发者提供一套系统化的性能优化方案。文章首先剖析了JVM内存管理机制的工作原理,然后通过对比分析不同垃圾收集器的适用场景及性能表现,为读者揭示了选择合适垃圾回收策略的数据支持。接下来,结合线程管理和JIT编译优化等高级话题,文章详细阐述了如何利用现代JVM提供的丰富工具进行问题诊断和性能监控。最后,通过实际案例分析,展示了性能调优过程中可能遇到的挑战及应对策略,确保读者能够将理论运用于实践,有效提升Java应用的性能。 【
155 10
|
2月前
|
监控 算法 Java
深入理解Java虚拟机:JVM调优的实用策略
在Java应用开发中,性能优化常常成为提升系统响应速度和处理能力的关键。本文将探讨Java虚拟机(JVM)调优的核心概念,包括垃圾回收、内存管理和编译器优化等方面,并提供一系列经过验证的调优技巧。通过这些实践指导,开发人员可以有效减少延迟,提高吞吐量,确保应用稳定运行。 【7月更文挑战第16天】
|
2月前
|
JSON Java BI
一次Java性能调优实践【代码+JVM 性能提升70%】
这是我第一次对系统进行调优,涉及代码和JVM层面的调优。如果你能看到最后的话,或许会对你日常的开发有帮助,可以避免像我一样,犯一些低级别的错误。本次调优的代码是埋点系统中的报表分析功能,小公司,开发结束后,没有Code Review环节,所以下面某些问题,也许在Code Review环节就可以避免。
138 0
一次Java性能调优实践【代码+JVM 性能提升70%】
|
2月前
|
监控 算法 Java
深入探索Java虚拟机:性能监控与调优实践
在面对日益复杂的企业级应用时,Java虚拟机(JVM)的性能监控和调优显得尤为重要。本文将深入探讨JVM的内部机制,分析常见的性能瓶颈,并提供一系列针对性的调优策略。通过实际案例分析,我们将展示如何运用现代工具对JVM进行监控、诊断及优化,以提升Java应用的性能和稳定性。
|
1月前
|
Arthas Prometheus 监控
使用JDK自带工具调优JVM的常用命令
使用JDK自带工具调优JVM的常用命令