TABLE OF CONTENTS

  1. JVM调优的参数都有哪些?
    1. 堆分配参数
  2. JVM调优思路
    1. 1、内存管理
    2. 2、垃圾回收
    3. 3、线程管理
    4. 4、代码优化
    5. 5、内存泄漏分析
    6. 6、堆转储文件
  3. 实践
    1. 堆分配参数一
    2. 堆分配参数二
    3. 堆溢出处理
    4. Java栈配置
    5. 方法区
    6. 直接内存配置
  4. 参考资料

这篇文章讲解下JVM调优基础知识,后面会再单独开一篇文章讲解下JVM调优的思路。

JVM(Java虚拟机)调优是优化Java应用程序性能和内存使用的过程。调优可以帮助应用程序更有效地利用内存、提高吞吐量和降低延迟。

JVM调优的参数都有哪些?

JVM调优的目标是什么?通过JVM的学习,我们知道频繁的GC会导致程序挂起,垃圾回收占用CPU资源,因此性能调优中就包括对内存的优化,减少GC。

JVM调优主要就是调整年轻代、老年代、元空间的内存空间大小及使用的垃圾回收器类型。

堆分配参数

示例:-Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8

Params Description
Xms 最小堆容量
Xmx 最大堆容量
Xmn 新生代容量 <==> Eden + Survivor A + Survivor B
PrintGCDetail 记录GC日志
SurvivorRatio 新生代中Eden与Survivor区域的比值,默认值为8
PretenureSizeThreshold 对象大小大于该值,直接分配至老年代
MaxTenuringThreshold 大于该阈值时晋升至老年代,默认值为15
HandlePromotionFailure 是否允许担保失败
ParalleGCThreads 设置并行GC时进行内存回收的线程数

JVM调优思路

1、内存管理

堆内存设置

1
java -Xms512m -Xmx2g -jar your-application.jar

永生代/元数据区大小

1
java -XX:MaxMetaspaceSize=256m -jar your-application.jar

2、垃圾回收

选择合适的垃圾收集器

根据硬件配置如CPU核数线程数,以及应用程序的特性,不同内存区域的垃圾收集,选择合适的垃圾收集器,如G1、CMS、Parallel等

1
2
java -XX:+UseG1GC -jar your-application.jar

垃圾回收日志: 启用垃圾回收日志以进行性能分析和调优。

1
2
java -Xloggc:gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -jar your-application.jar

3、线程管理

线程栈大小:根据应用程序的线程需求设置线程栈大小。

1
java -Xss256k -jar your-application.jar

并发线程数: 根据硬件配置和应用程序性质设置并发线程数。

1
java -XX:ParallelGCThreads=4 -jar your-application.jar

4、代码优化

性能分析: 使用性能分析工具(如VisualVM、YourKit)来识别和优化性能瓶颈。示例:

bash
Copy code
jvisualvm
代码检查: 使用静态分析工具(如Checkstyle、FindBugs)检查代码质量,消除潜在的性能问题。

5、内存泄漏分析

6、堆转储文件

在内存溢出(OOM)时生成堆转储文件,以进行分析。

1
2
java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dump.hprof -jar your-application.jar

实践

堆分配参数一

Command Description
-XX:+PrintGC 虚拟机启动后,只要遇到GC就会打印日志
-XX:+UseSerialGC 配置串行回收器
-XX:+PrintCommandLineFlags 在控制台输出JVM的配置参数。
-XX:+PrintGCDetails 可以查看详细信息,包括各个区的情况
-Xms5m 设置最小堆大小为5M
-Xmx20M 设置最大堆大小为20M

实际工作中,可以将初始的堆大小与最大堆大小设置相等,好处是可以减少程序运行时的垃圾回收次数。通常是配置在Tomcat中,如catalina.sh

堆分配参数二

Command Description
-Xmn5M 设置新生代的大小为5M,年老代+新生代大小=堆大小,这个参数对系统性能和GC行为有较大的影响,新生代大小一般设置为堆空间的1/3到1/4左右
-XX:SurvivorRatio 设置新生代中eden空间和from或to空间的比例(from和to空间大小相同),含义:-XX:SurvivorRatio=eden/from=eden/to
-XX:NewRatio 除了可以通过-Xmn参数设置新生代的绝对大小,还可以-XX:NewRatio通过设置新生代和年老代的比例:-XX:NewRatio=老年代/新生代

实际工作中,应该根据系统的特点做出合理配置,基本策略:尽可能将对象预留在新生代,减少老年代的GC次数。比如系统内的实例对象大多是一直使用,那么老年代可以分配大一些。

堆溢出处理

如果堆空间不足,可以出现OOM报错,可以通过

Command Description
-XX:+HeapDumpOnOutOfMemoryError 可以在内存溢出时与下面的参数配合,导出整个堆信息
-XX:HeapDumpPath 设置导出堆的存放路径

内存分析工具:Eclipse Memory Analyzer (MAT)、VisualVM、jmap命令

Java栈配置

Command Description
-Xss 指定线程的最大栈空间,决定了函数可调用的最大深度

方法区

Command Description
-XX:MaxPermSize 方法区最大大小,默认为64MB,如果运行时产生大量的类,就需要设置一个相对合适的方法去,避免出现永久区OOM问题
1
-XX:PermSize=64M -XX:MaxPermSize=64MB

直接内存配置

NIO中用得较多

-XX:MaxDirectMemorySize,如果不设置,默认值为最大堆空间即-Xmx,直接内存到达上限后就会触发垃圾回收,也会导致OOM。

参考资料

Java HotSpot VM Options
JVM系列三:JVM参数设置、分析

声明:本站所有文章均为原创或翻译,遵循署名 - 非商业性使用 - 禁止演绎 4.0 国际许可协议,如需转载请确保您对该协议有足够了解,并附上作者名 (Tsukasa) 及原文地址