JVM参数设置及优化

本文中一些参数基于JDK8,我们在优化过程中,需要同时关注FullGC和YoungGC,尽可能避免stop-the-world。

JVM内存分区

JVM进程占用内存 = 堆内存 + 线程数*线程栈 + 元空间 + 堆外内存

线程数可以利用jstack $PID | more观察当前JVM中所有线程,可以优化部分不必要的线程,降低内存使用同时也避免线程切换的开销。

栈Stack

存储局部变量等,默认为1M

堆Heap

存储对象实例,包含新生代,老年代

元Metaspace

存储类定义

堆外Off-heap

java.nio.*等使用

内存相关参数

这里主要利用jstat -gcutil $PID, jmap -heap $PID, jmap -histo $PID | more几个常用的命令的结果作为优化的参考。

-Xss[m|k]

每个线程栈大小

-Xms[g|m|k] or -XX:InitialHeapSize

初始堆内存大小

-Xmx[g|m|k] or -XX:MaxHeapSize

最大堆内存大小

-Xmn[g|m|k] or -XX:NewSize and -XX:MaxNewSize

新生代大小,考虑GC时最坏情况,不建议新生代空间大于老年代

-XX:NewRatio=

老年代与新生代的大小比例

-XX:SurvivorRatio=

Eden区与Survivor区的大小比例

-XX:MetaspaceSize=[g|m|k] and -XX:MaxMetaspaceSize=[g|m|k]

元数据大小,堆外分配内存

GC相关参数

-XX:+UseParallelGC

JDK8默认GC算法

-XX:+UseConcMarkSweepGC

使用CMS算法

-XX:+UseG1GC

使用G1算法,生产环境谨慎

-XX:MaxTenuringThreshold=

新生代中对象存活次数,超过n后提升到老年代

-XX:+PrintGCDetails and -XX:+PrintTenuringDistribution

打印GC信息,提供优化参考

优化方案

  1. 注意ArrayList, HashMap, StringBuilder等扩容问题
  2. Thread Safe的对象全局重用,非Thread Safe的对象ThreadLocal重用
  3. 局部变量更多采用基础类型
  4. 控制长生命周期对象数量,比如连接池、线程池、缓存等

参考 用于JVM性能调优的Java命令行选项