JVM调试
1、tomcat 设置JVM信息以及日志打印路径(特意设置较小 导致频繁GC)
set "JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG% -server -Xms128m -Xmx128m -XX:PermSize=64M -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:D:/CCshare/User/other/apache-tomcat-8.0.15_pay/gclog/gc.log"
2、日志解读
-verbose:gc:
表示输出虚拟机中GC的详细情况,使用后输出如下:
12.537: [Full GC 168K->97K(1984K), 0.0253873 secs]
解读如下:
12.537表示距离tomcat启动时间为12.537秒;箭头前后的数据168K和97K分别表示垃圾收集GC前后所有存活对象使用的内存容量,说明有168K-97K=71K的对象容量被回收,括号内的数据1984K为堆内存的总容量,收集所需要的时间是0.0253873秒(这个时间在每次执行的时候会有所不同)
备注:GC会暂用CPU时间片,有可能造成应用程序在某个时刻极短的停顿.
使用UseParNewGC垃圾回收区
//由于图片上传总是失败 后面补充各种垃圾回收器的选择和优劣
数据示例:
CommandLine flags: -XX:InitialHeapSize=268435456 -XX:MaxHeapSize=541065216 -XX:MaxNewSize=180355072 -XX:MaxTenuringThreshold=6 -XX:MetaspaceSize=67108864 -XX:NewSize=180355072 -XX:OldPLABSize=16 -XX:OldSize=360710144 -XX:+PrintGC -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintTenuringDistribution -XX:+UseConcMarkSweepGC -XX:-UseLargePagesIndividualAllocation -XX:+UseParNewGC
启动之后GC日志打印配置信息
Minor GC
7.237: [GC (Allocation Failure) 7.237: [ParNew Desired survivor size 9011200 bytes, new threshold 1 (max 6)- age 1: 16246832 bytes, 16246832 total: 158528K->17600K(158528K), 0.0248950 secs] 199144K->64521K(244544K), 0.0249776 secs] [Times: user=0.05 sys=0.00, real=0.03 secs] 7.262: Total time for which application threads were stopped: 0.0251616 seconds, Stopping threads took: 0.0000311 seconds
Full/Major GC
7.268: [GC (CMS Initial Mark) [1 CMS-initial-mark: 46921K(86016K)] 67227K(244544K), 0.0030202 secs] [Times: user=0.03 sys=0.00, real=0.00 secs]
7.271: Total time for which application threads were stopped: 0.0031401 seconds, Stopping threads took: 0.0000249 seconds
7.271: [CMS-concurrent-mark-start]
7.318: [CMS-concurrent-mark: 0.047/0.047 secs] [Times: user=0.06 sys=0.03, real=0.05 secs]
7.318: [CMS-concurrent-preclean-start]
7.319: [CMS-concurrent-preclean: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
7.319: [CMS-concurrent-abortable-preclean-start]
7.696: [CMS-concurrent-abortable-preclean: 0.077/0.377 secs] [Times: user=0.42 sys=0.09, real=0.38 secs]
7.697: [GC (CMS Final Remark) [YG occupancy: 110476 K (158528 K)]7.697: [Rescan (parallel) , 0.0231174 secs]7.720: [weak refs processing, 0.0000982 secs]7.720: [class unloading, 0.0024069 secs]7.723: [scrub symbol table, 0.0016612 secs]7.724: [scrub string table, 0.0001395 secs][1 CMS-remark: 46921K(86016K)] 157397K(244544K), 0.0283315 secs] [Times: user=0.06 sys=0.00, real=0.03 secs]
7.725: Total time for which application threads were stopped: 0.0288270 seconds, Stopping threads took: 0.0003586 seconds
7.725: [CMS-concurrent-sweep-start]
7.740: [CMS-concurrent-sweep: 0.014/0.014 secs] [Times: user=0.05 sys=0.00, real=0.01 secs]
7.740: [CMS-concurrent-reset-start]
7.742: [CMS-concurrent-reset: 0.002/0.002 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
7.268: [GC (CMS Initial Mark) [1 CMS-initial-mark: 46921K(86016K)] 67227K(244544K), 0.0030202 secs] [Times: user=0.03 sys=0.00, real=0.00 secs]
7.271: Total time for which application threads were stopped: 0.0031401 seconds, Stopping threads took: 0.0000249 seconds
是CMS中两次stop-the-world事件中的一次。它有两个目标:一是标记老年代中所有的GC Roots;二是标记被年轻代中活着的对象引用的对象。
开始使用CMS回收器进行老年代回收。初始标记(CMS-initial-mark)阶段,这个阶段标记由根可以直接到达的对象,标记期间整个应用线程会暂停。
老年代容量为86016K,CMS 回收器在空间占用达到 46921K时被触发
应用程序暂停 0.0031401 seconds
7.271: [CMS-concurrent-mark-start]
开始并发标记(concurrent-mark-start) 阶段,在第一个阶段被暂停的线程重新开始运行,由前阶段标记过的对象出发,所有可到达的对象都在本阶段中标记。
7.318: [CMS-concurrent-mark: 0.047/0.047 secs] [Times: user=0.06 sys=0.03, real=0.05 secs]
并发标记阶段结束,占用 0.047秒CPU时间, 0.047 秒墙钟时间(也包含线程让出CPU给其他线程执行的时间)
7.318: [CMS-concurrent-preclean-start]
开始预清理阶段
预清理也是一个并发执行的阶段。在本阶段,会查找前一阶段执行过程中,从新生代晋升或新分配或被更新的对象。通过并发地重新扫描这些对象,预清理阶段可以减少下一个stop-the-world 重新标记阶段的工作量。
7.319: [CMS-concurrent-preclean: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
预清理阶段费时 0.001秒CPU时间,0.001秒墙钟时间。
7.319: [CMS-concurrent-abortable-preclean-start]
7.696: [CMS-concurrent-abortable-preclean: 0.077/0.377 secs] [Times: user=0.42 sys=0.09, real=0.38 secs]
加入此阶段的目的是使cms gc更加可控一些,作用也是执行一些预清理,以减少Rescan阶段造成应用暂停的时间
7.697: [GC (CMS Final Remark) [YG occupancy: 110476 K (158528 K)]7.697: [Rescan (parallel) , 0.0231174 secs]7.720: [weak refs processing, 0.0000982 secs]7.720: [class unloading, 0.0024069 secs]7.723: [scrub symbol table, 0.0016612 secs]7.724: [scrub string table, 0.0001395 secs][1 CMS-remark: 46921K(86016K)] 157397K(244544K), 0.0283315 secs] [Times: user=0.06 sys=0.00, real=0.03 secs]
7.725: Total time for which application threads were stopped: 0.0288270 seconds, Stopping threads took: 0.0003586 seconds
这个阶段是CMS中第二个并且是最后一个STW的阶段。该阶段的任务是完成标记整个年老代的所有的存活对象。由于之前的预处理是并发的,它可能跟不上应用程序改变的速度,这个时候,STW是非常需要的来完成这个严酷考验的阶段。
通常CMS尽量运行Final Remark阶段在年轻代是足够干净的时候,目的是消除紧接着的连续的几个STW阶段。
7.725: [CMS-concurrent-sweep-start]
7.740: [CMS-concurrent-sweep: 0.014/0.014 secs] [Times: user=0.05 sys=0.00, real=0.01 secs]
和应用线程同时进行,不需要STW。这个阶段的目的就是移除那些不用的对象,回收他们占用的空间并且为将来使用。
7.740: [CMS-concurrent-reset-start]
7.742: [CMS-concurrent-reset: 0.002/0.002 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
这个阶段并发执行,重新设置CMS算法内部的数据结构,准备下一个CMS生命周期的使用。