总结JVM调优的几个入手点:
1: 升级 JVM 版本。
这个就不多说了。JVM自身也是在不断完善的。
2:选择正确的GC策略。
收集器设置
-XX:+UseSerialGC:设置串行收集器
-XX:+UseParallelGC:设置并行收集器
-XX:+UseParalledlOldGC:设置并行年老代收集器
-XX:+UseConcMarkSweepGC:设置并发收集器
垃圾回收统计信息
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintGCApplicationConcurrentTime:打印每次垃圾回收前,程序未中断的执行时间
-XX:+PrintGCApplicationStoppedTime:打印垃圾回收期间程序暂停的时间。
-XX:PrintHeapAtGC:打印GC前后的详细堆栈信息
-Xloggc:filename:把相关日志信息记录到文件
3:合理设置JVM堆内各个区域的大小。
堆设置
-Xms:初始堆大小
-Xmx:最大堆大小
-XX:NewSize=n:设置年轻代大小
-XX:NewRatio=n:设置年轻代和年老代的比值。
-XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。
-XX:MaxPermSize=n:设置持久代大小
年轻代大小的选择原则尽可能设置足够大的空间。年轻代的内存回收频率很高,需考虑系统的最低响应时间限制。
年老代大小的选择原则比较复杂。
如果堆设置小了,可能会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。
整个堆大小=年轻代大小 + 年老代大小。一般设置年轻代大小为整个堆得3/8.
设置JVM堆大小时保持设置的上下限相等,减小分配堆大小时的消耗。
4: 程序中需注意的地方。
不要显式的调用System.gc()方法。如果JVM没有禁掉程序gc的话,这样的语句会造成full gc。频繁调度加重系统负担。
尽可能少分配大的临时对象。临时对象有可能会被放到年老代中,这部分内存只有在full gc时才会被回收。
频繁无限制的分配临时对象,会造成年老代暴涨。程序运行时间久则变慢的原因也是在这里。
5:几个典型的JVM设置
java -Xmx1024m -Xms1024m -Xmn384m -Xss128k
java -Xmx1024m -Xms1024m -Xss128k -XX:NewRatio=3 -XX:SurvivorRatio=3
-XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0