啊,面试的时候因为简历提到了JVM调优,所以在这里也总结一下。
其实一般情况下,我们对于JVM进行调优,都是首先多线程进行完一拨优化了,然后线程了安全了,线程池什么的都用了,最后一步才会轮到对JVM进行调优,GC调优等等,而且在这之后,我们还必须经过大量的压测才能证明出是否调优真的优化了。
目标
首先我们应该清楚,我们JVM调优的目的是什么?
- 减少Full GC的次数
- 降低stw的时间,提高吞吐量
- 全力阻止oom的发生
- 尽力不让老年代的内存占用达到上限
方法
现在来主要说一下进行JVM调优的方案。
- 首先我们应该准备一下Jprofiler做一个堆栈跟踪,通过观察堆栈上面对象的信息和GC的日志,可以确定当前应用程序平台的问题出现在哪里。
- 确定JVM调优的方向并且量化目标。
- 不断的去对比调优前后,压测的结果。
然后介绍几个之前在京东做JVM调优的时候,会设置的几个常用的参数
通过-Dfile.encoding指明编码格式:
-agentlib:jdwp是一个菜单选项,后面的参数意思是:通过socket套接字进行连接到JVM,并且暴露tcp/ip端口,suspend代表调试器立即开始执行,而不是碰到连接jvm成功之后才开始执行。
紧接着,-XX:+ HeapDumpOnOutOfMemoryError告诉HotSpot虚拟机要生成一个堆转储时从Java堆或永久代的分配不能满足。使用此选项运行不会产生任何开销,因此对于OutOfMemoryError需要很长时间才能浮出水面的生产系统很有用。当java.lang.OutOfMemoryError被抛出,将创建一个堆转储文件。后面的-Xx:HeapDumpPath选项指定备用文件名或目录。
后面的参数,主要是GC相关的配置了:
Xms 是指设定程序启动时占用内存大小。一般来讲,大点,程序会启动的快一点,但是也可能会导致机器暂时间变慢。
Xmx 是指设定程序运行期间最大可占用的内存大小。如果程序运行需要占用更多的内存,超出了这个设置值,就会抛出OutOfMemory异常。
-Djava.net.preferIPv4Stack=true代表告诉tomcat只识别ipv4。
-XX:Newsize : 设置年轻代(Yong Generation)的初始值大小。
-XX:Maxnewsize:设置年轻代(Yong Generation)的最大值大小。
-XX:+UseG1GC:指明使用G1GC,也就是使用分代收集算法作为垃圾回收的主要算法,后面也针对G1GC进行了一些相关的参数配置。
-XX:MaxGCPauseMillis=90:设置一个目标最大暂停时间. 这是一个理想化的目标,JVM会尽可能的完成它. 因此,这个目标不一定能达到。
-XX:InitiatingHeapOccupancyPercent=70:整个堆栈使用达到百分之多少的时候,启动GC周期. 基于整个堆,不仅仅是其中的某个代的占用情况,G1根据这个值来判断是否要触发GC周期,在这里代表达到70%开始GC
-XX:ParallelGCThreads=8:GC在并行处理阶段试验多少个线程
-XX:ConcGCThreads=6:并发收集的时候使用多少个线程
以下几个配置参数,是基于JVM GC格式的日志进行设置的:
-XX:+PrintGCDetails: 输出详细GC日志
-XX:+PrintReferenceGC: 打印年轻代各个引用的数量以及时长
-XX:+PrintGCDateStamps: 输出GC的时间戳
-XX:+PrintTenuringDistribution: 输出显示在survivor空间里面有效的对象的岁数情况
-XX:+PrintHeapAtGC: 在进行GC的前后打印出堆的信息
-Xloggc:…/logs/gc.log: GC日志的打印地址