推荐投放项目JVM总结

做推荐投放三年了,从来没有发生过GC相关的问题(🐂,ps:访问量和数据量还是挺大的),所以有必要总结一下相关JVM参数。

一. jvm参数截图

二. jvm参数说明

1
2
3
4
5
6
7
8
9
10
11
12
13
-Djava.awt.headless=true -Djava.net.preferIPv4Stack=true
-Dlocal.ip=10.10.34.11 -Dcom.tc.productkey.path=/opt/mobil/terracotta-license.key
-Djava.util.Arrays.useLegacyMergeSort=true -Dfile.encoding=UTF-8
-server -Xmx9g -Xms9g -XX:PermSize=96m -XX:MaxPermSize=96m -Xss256k
-XX:MaxDirectMemorySize=17G -XX:+UseG1GC -XX:MaxGCPauseMillis=200
-XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=40
-XX:ConcGCThreads=10 -XX:+PrintGCDateStamps -Xloggc:../logs/gc.log
-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=50M
-XX:HeapDumpPath=../logs/java.hprof -XX:+DisableExplicitGC
-XX:-OmitStackTraceInFastThrow -XX:+PrintCommandLineFlags
-XX:+UnlockCommercialFeatures -XX:+FlightRecorder
-XX:+HeapDumpOnOutOfMemoryError -Djava.rmi.server.hostname=10.10.34.11
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=1099

1.-server

JVM以服务器模式来启动。

2.G1相关:

  • -XX:+UseG1GC: 使用G1垃圾回收器
  • -XX:MaxGCPauseMillis: gc最长暂停时间,需要根据堆的大小来设置。
  • -XX:G1ReservePercent: 设置作为空闲空间的预留内存百分比,以降低目标空间溢出的风险。默认值是 10%。增加或减少百分比时,需要评估Java堆的量。
  • -XX:InitiatingHeapOccupancyPercent:设置触发标记周期的Java堆占用率阈值(默认是45%)
  • -XX:ConcGCThreads:并发标记阶段的线程数。

3.持久代相关

  • PermSize: 持久代的内存
  • MaxPermSize: 持久代的最大内存

两者通常设置为一致即可。

4.堆相关

  • Xmx: 堆最大内存
  • Xms: 堆初始化内存

为了减少内存分配的开销,两个参数通常是一样的。

5.堆外内存

  • MaxDirectMemorySize: 堆外内存大小

如果不设置,“几乎”默认等于Xmx,也可以根据需要的数量进行设置。

6. OmitStackTraceInFastThrow

OmitStackTraceInFastThrow的意思是当大量throw异常时是否在日志中忽略部分日志(可能太长了),通常不使用这个特性(便于问题分析)。

7.自定义配置

-Dlocal.ip和-Dcom.tc.productkey.path便于程序内部通过System.getProperty(“xxx”)来获取,有时候程序内部需要知道本机IP地址,可以使用这种形式:local.ip。com.tc.productkey.path就是bigmemory需要的。

8.gc文件相关:

  • -Xloggc:gc-log的位置
  • -XX:+UseGCLogFileRotation: gc-log是否自动卷
  • -XX:NumberOfGCLogFiles: gc-log文件个数
  • -XX:GCLogFileSize: 每个gc-log的大小
  • -XX:+PrintGCDateStamps: 在gc日志添加时间戳

9.-XX:+HeapDumpOnOutOfMemoryError和 -XX:HeapDumpPath

OOM发生后会将内存镜像Dump到磁盘,有利于后期使用MAT这样的工具进行问题定位。 -XX:HeapDumpPath是dump文件的全路径。

10. -XX:+UnlockCommercialFeatures和-XX:+FlightRecorder

使用飞行记录器(商业功能)(-XX:+FlightRecorder)必须解锁商业特性:-XX:+UnlockCommercialFeatures

11. jmx相关:

很多Java程序会将一些系统状态(例如JVM使用等)放在JMX,应用开发者也会这么做,如果要JMX对外开放可以添加如下配置:

序号 参数 说明
1 -Djava.rmi.server.hostname 对外使用rmi进行通信
2 -Dcom.sun.management.jmxremote 启动jmx
3 -Dcom.sun.management.jmxremote.port jmx的port
4 -Dcom.sun.management.jmxremote.ssl jmx是否使用ssl
5 -Dcom.sun.management.jmxremote.authenticate jmx是否使用密码

12.其他:

  • -Djava.awt.headless: 忽略显示设备和键鼠,通常为后端服务器时候
  • -Djava.net.preferIPv4Stack: 优先使用IPV4(因为目前很多服务器已经配置了IPV6)
  • -XX:+DisableExplicitGC: 禁止显式的执行System.gc()
  • -XX:+PrintCommandLineFlags: 将当前JVM中与默认配置不同的参数打印出来(这个很有用)
  • -Dfile.encoding: 默认字符集, 它是在java虚拟机启动时决定的,依赖于java虚拟机所在的操作系统的区域以及字符集,通过这个配置可以强制为某个字符集(避免修改操作系统)
  • -Djava.util.Arrays.useLegacyMergeSort:在Java 6中Arrays.sort()和Collections.sort()使用的是MergeSort,而在Java 7中,内部实现换成了TimSort,其对对象间比较的实现要求更加严格,为了在JDK7中中解决,可以使用如下两种方法:

(1) 更改内部实现

1
2
3
4
public int compare(ComparatorTest o1, ComparatorTest o2) {
return o1.getValue() == o2.getValue() ? 0 :
(o1.getValue() > o2.getValue() ? 1 : -1);
}

(2) Java 7预留了一个接口以便于用户继续使用Java 6的排序算法

1
-Djava.util.Arrays.useLegacyMergeSort=true

三、其他重要参数

1. -XX:OnOutOfMemoryError

当发生OOM时,通过上面这个配置可以发出一个自定义脚本(例如短信微信报警等),对于快速发现OOM问题很有帮助,甚至有些分布式节点(例如HBase的RegionServer)可以配置kill -9,例如如下所示:

1
-XX:OnOutOfMemoryError ="sh /xx/xx/alert.sh"
1
-XX:OnOutOfMemoryError="kill -9 %p"

2.-XX:+TraceClassLoading(排查NoSuchMethodException和ClassNotFoundException等问题的利器)

上述配置可以在JVM启动时,打印出所有类是从哪个jar包加载进来的,对于解决包冲突很有帮助。有些特殊情况,maven已经解决了冲突,但是还会出现,例如某些容器有些自己的包(曾经碰到resin的hessian包)

四. 参考资料

1.JVM实用参数系列

2.Java常见问题排查方法视频 毕玄的稿件

1
百度网盘:链接:http://pan.baidu.com/s/1dFy7zHn 密码:r8y6

3.Java常见问题排查方法文稿

4.JVM日志和参数的理解 益军写的