TABLE OF CONTENTS
这篇文章讲解下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 | java -XX:+UseG1GC -jar your-application.jar |
垃圾回收日志: 启用垃圾回收日志以进行性能分析和调优。
1 | 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 | 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) 及原文地址