先阐明下这里是测试环境试验,并且JVM调优要依据我的项目和运行理论状况来进行调整,极其状况不可循序渐进

测试环境如下:1个1核2线程的CPU(2个逻辑CPU),8G内存,JDK:1.7,tomcat:8.5.70,JVM参数为默认

先在 catalina.sh 中增加参数打印GC信息到日志文件
JAVA_OPTS="-XX:+PrintGCDetails -Xloggc:/opt/logs/gc.log"

优化项1

默认状况堆最小空间和最大空间不统一,为了防止每次垃圾回收实现后JVM从新分配内存,调整为统一,默认最小为总内存1/64,最大为1/4 通过计算有肯定偏差,手动设置为最小和最大都为2G

JAVA_OPTS="-Xms2G -Xmx2G -XX:+PrintGCDetails -Xloggc:/opt/logs/gc.log"

启动后通过jstat -gc -h 10 pid 1s 查看pid jvm中各空间应用状况 1秒刷新一次 保留10行

发现S1 大小在YOUNG GC后会发生变化,通过材料查问发现可能是主动调整性能(猜想)

(猜想) S1应用过程中, 将上一次复制过去的数据清理后存活的大小按肯定比例寄存, 即:不占据过多空间。S0应用过程中, 将S1扩容至S0大小,避免S0和Eden数据复制过去再大幅度扩容

我增加了-XX:SurvivorRatio=8 让S0 和 S1 同样大小 占年老代1/10, 这样young GC 后 S0 S1容量不再发生变化,便于调试变动的值

内存调配到这里完结了,上面就是垃圾回收器的抉择,官网JDK7这方面形容的比拟少,这里参考8的官网文档摸索一下

垃圾回收器次要思考在老年代的回收,因为青年代大部分不到15岁就被革除了(一次young gc 算一岁,默认15次)

CMS(Concurrent Mark Sweep) 次要用于老年代的垃圾回收, 年老代仍实用串行或并行的形式进行垃圾回收, 相比于并行收集器,采纳并发标记来缩小STW工夫。但同样有肯定的毛病,比方老年代革除后有空间碎片,如果有一个大对象进入老年代,没有间断的空间进行过存储,将进行一次不必要的Full GC,而且在并行标记时也会占用更多的CPU。

革除步骤如下:

  1. 初始标记(CMS initial mark):独占CPU,stop-the-world, 仅标记GCroots能间接关联的对象,速度比拟快;
  2. 并发标记(CMS concurrent mark):能够和用户线程并发执行,通过GCRoots Tracing 标记所有可达对象;
  3. 从新标记(CMS remark):独占CPU,stop-the-world, 对并发标记阶段用户线程运行产生的垃圾对象进行标记修改,以及更新逃逸对象;
  4. 并发清理(CMS concurrent sweep):能够和用户线程并发执行,清理在反复标记中被标记为可回收的对象。

CMS 收集器在并发收集周期中两次暂停应用程序。第一个暂停是将可从根间接拜访的对象(例如,来自应用程序线程堆栈和寄存器的对象援用、动态对象等)和堆中的其余中央(例如,年老代)标记为流动对象。第一次暂停称为初始标记。第二次暂停呈现在并发标记完结时,它会在 CMS 收集器实现并发标记后查找因为应用程序线程更新对象中的援用而被并发跟踪脱漏的对象叫做从新标记。

G1(Garbage-First) 垃圾收集器是一种服务器式垃圾收集器,针对具备大内存的多处理器机器。它试图以高概率满足垃圾收集 (GC) 暂停工夫指标,同时实现高吞吐量。全堆操作(例如全局标记)与应用程序线程同时执行。这能够避免与堆或实时数据大小成正比的中断。其余的垃圾回收相比, G1弱化了分代的状况, 用了Region的构造来代替新生代年轻代。

材料:
JAVA7官网JVM调优白皮书
JAVA7官网JVM参数
JAVA各版本官网文档
CMS垃圾回收器
G1垃圾回收期
借鉴了大神的CMS与G1区别