3.-XX:+GCLockerInvokesConcurrent
我们犯过的错,不是所有Concurrent字样的参数都是好参数,加上之后,原本遇上JNI GCLocker只需要补偿YGC就够的,变成要执行YGC + CMS GC了 。
2.4 内存大小的设置其实JVM除了显式设置的-Xmx堆内存,还有一堆其他占内存的地方(堆外内存,线程栈,永久代,二进制代码cache),在容量规划的时候要留意 。
关键业务系统的服务器上内存一般都是够的,所以尽管设得宽松点 。
1. -Xmx, -Xms,堆内存大小,2~4G均可 。
2. -Xmn or -XX:NewSize or -XX:NewRatio
JDK默认新生代占堆大小的1/3,个人喜欢把对半分,因为增大新生代能减少GC的频率,如果老生代里没多少长期对象的话,占2/3通常太多了 。可以用-Xmn 直接赋值(等于-XX:NewSize and -XX:MaxNewSize同值的缩写),或把NewRatio设为1来对半分 。
3. -XX: PermSize=128m -XX:MaxPermSize=512m (JDK7)-XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m(JDK8)
现在的应用有Hibernate/Spring这些闹腾的家伙AOP之后类都比较多,可以一开始就把初始值从64M设到128M(否则第一次自动扩张会造成大约3秒的JVM停顿),并设一个更大的Max值以求保险 。
JDK8的永生代几乎可用完机器的所有内存,同样设一个128M的初始值,512M的最大值保护一下 。
2.5 其他内存大小的设置1. -Xss
在堆之外,线程占用栈内存,默认每条线程为1M(以前是256K) 。存放方法调用出参入参的栈,局部变量,标量替换后掉局部变量等,有人喜欢把它设回256k如Cassandra,节约内存并开更多线程,有人则会在遇到错误后把它再设大点,特别是有很深的JSON解析之类的递归调用时 。
2. -XX:SurvivorRatio
新生代中每个存活区的大小,默认为8,即1/10的新生代 1/(SurvivorRatio+2),有人喜欢设小点省点给新生代,但要避免太小使得存活区放不下临时对象而被迫晋升到老生代,还是从GC日志里看实际情况了 。
3. -XX:MaxDirectMemorySize
堆外内存的最大值,默认为Heap区总内存减去一个Survivor区的大小,详见《Netty之堆外内存扫盲篇》,如果肯定用不了这么多,也可以把它主动设小,来获得一个比较清晰内存占用预估值,特别是在容器里 。
4. -XX:ReservedCodeCacheSize
JIT编译后二进制代码的存放区,满了之后就不再编译,对性能影响很大 。JDK7默认不开多层编译48M,开了96M,而JDK8默认开多层编译240M 。可以在JMX里看看CodeCache的占用情况,也可以用VJTools里的vjtop来看,JDK7下默认的48M可以设大点,不抠这么点 。

文章插图
3. 监控篇JVM输出的各种日志,如果未指定路径,通常会生成到运行应用的相同目录,为了避免有时候在不同的地方执行启动脚本,一般将日志路径集中设到一个固定的地方 。
3.1 监控建议配置1. -XX:+PrintCommandLineFlags
运维有时会对启动参数做一些临时的更改,将每次启动的参数输出到stdout,将来有据可查 。打印出来的是命令行里设置了的参数以及因为这些参数隐式影响的参数,比如开了CMS后,-XX:+UseParNewGC也被自动打开 。
2. -XX:-OmitStackTraceInFastThrow
为异常设置StackTrace是个昂贵的操作,所以当应用在相同地方抛出相同的异常N次(两万?)之后,JVM会对某些特定异常如NPE,数组越界等进行优化,不再带上异常栈 。此时,你可能会看到日志里一条条Nul Point Exception,而之前输出完整栈的日志早被滚动到不知哪里去了,也就完全不知道这NPE发生在什么地方,欲哭无泪 。所以,将它禁止吧,ElasticSearch也这样干 。
3.2 Crash文件1. -XX:ErrorFile
JVM crash时,hotspot 会生成一个error文件,提供JVM状态信息的细节 。如前所述,将其输出到固定目录,避免到时会到处找这文件 。文件名中的%p会被自动替换为应用的PID
-XX:ErrorFile=${LOGDIR}/hs_err_%p.log
2. coredump
当然,更好的做法是生成coredump,从CoreDump能够转出Heap Dump 和 Thread Dump 还有crash的地方,非常实用 。
在启动脚本里加上 ulimit -c unlimited或其他的设置方式,如果有root权限,设一下输出目录更好
echo "/{MYLOGDIR}/coredump.%p" > /proc/sys/kernel/core_pattern
什么?你不知道coredump有什么用?看来你是没遇过JVM Segment Fault的幸福人 。
3. -XX:+
HeapDumpOnOutOfMemoryError(可选)
在Out Of Memory,JVM快死掉的时候,输出Heap Dump到指定文件 。不然开发很多时候还真不知道怎么重现错误 。
路径只指向目录,JVM会保持文件名的唯一性,叫java_pid${pid}.hprof 。因为如果指向文件,而文件已存在,反而不能写入 。
推荐阅读
- 茶园病虫草害防治规程,茶园病虫草害的综合防治
- 春茶你喝对了吗,喝普洱茶有几个比较禁忌的地方
- Spring简单入门教程(二)spring的体系结构
- Bokeh是一个专门针对Web浏览器的交互式可视化Python库
- 你的代码“balance”怎么样?找到简洁性和可读性的平衡点
- 微软的Windows应用商店失败了,原因何在?
- 使用 Json 构建完整的管理系统界面
- 为什么你写的代码总是有 Bug?用它来保证 Go 代码质量
- Dcat Admin v1.5.2 发布,后端开发者的高颜值后台系统构建工具
- Comcast成为首个加入Mozilla TRR计划的网络服务提供商
