导致锯齿形图案的是 jconsole 本身。
要查看jconsole 或jvisualvm 的效果,您可以编写一个只有一个主循环的简单java 程序。例如
public static void main(String[] args) {
while (true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
}
只用一点点java -Xmx20m ... 执行它。这将帮助您更好地查看堆利用率,因为我接下来将使用的工具 jstat 以百分比形式打印利用率。
现在打开一个命令行窗口并执行jstat。您将需要 java 进程的 PID,可以使用 jps -l 找到它。
jstat -gcutil <PID>
它会打印出这样的东西
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0,00 0,00 69,34 0,00 14,48 17,19 0 0,000 0 0,000 0,000
关注伊甸园空间E。该值是空间当前容量的百分比。详情请查看jstat。
如果您一次又一次地执行该命令,您将看到伊甸园空间利用率不会增长。它保持在例如69,34。我在我的 Windows 上使用类似 linux watch 的命令以特定时间间隔重新运行该命令。见watch.bat
现在打开jconsole
jconsole <PID>
并一次又一次地执行jstat 命令。您会看到伊甸园空间不断增长,直到达到最大值并被垃圾回收。
这是jstat --gcutil <PID> 的输出,间隔为 1 秒。关注伊甸空间E。
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0,00 0,00 67,42 0,00 14,48 17,19 0 0,000 0 0,000 0,000
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0,00 0,00 67,42 0,00 14,48 17,19 0 0,000 0 0,000 0,000
# jconsole connected
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0,00 96,88 81,64 7,57 92,26 84,87 1 0,001 0 0,000 0,001
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0,00 96,88 84,66 7,57 92,26 84,87 1 0,001 0 0,000 0,001
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0,00 96,88 89,70 7,57 92,26 84,87 1 0,001 0 0,000 0,001
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0,00 96,88 91,70 7,57 92,26 84,87 1 0,001 0 0,000 0,001
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0,00 96,88 93,70 7,57 92,26 84,87 1 0,001 0 0,000 0,001
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0,00 96,88 95,70 7,57 92,26 84,87 1 0,001 0 0,000 0,001
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0,00 96,88 96,70 7,57 92,26 84,87 1 0,001 0 0,000 0,001
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0,00 96,88 98,71 7,57 92,26 84,87 1 0,001 0 0,000 0,001
# Garbage collected
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
100,00 0,00 1,13 14,06 94,75 89,26 2 0,003 0 0,000 0,003
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
100,00 0,00 3,00 14,06 94,75 89,26 2 0,003 0 0,000 0,003
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
100,00 0,00 5,75 14,06 94,75 89,26 2 0,003 0 0,000 0,003
如您所见... 在 jconsole 连接到进程后,伊甸园空间不断增长,直到它被垃圾收集。这会导致锯齿形图案。这是来自jvisualvm 的快照。
当您对您的 tomcat 进程执行相同操作时,您会发现类似的行为。唯一的区别是即使没有连接 jconsole,伊甸园空间也会略微增长。但是这种轻微的增长并不是你看到的之字形图案的原因。
这是我的 tomcat 的 jstat 输出。
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0,00 99,80 70,33 4,81 96,85 90,10 5 0,037 0 0,000 0,037
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0,00 99,80 70,33 4,81 96,85 90,10 5 0,037 0 0,000 0,037
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0,00 99,80 70,43 4,81 96,85 90,10 5 0,037 0 0,000 0,037
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0,00 99,80 70,43 4,81 96,85 90,10 5 0,037 0 0,000 0,037
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0,00 99,80 70,43 4,81 96,85 90,10 5 0,037 0 0,000 0,037
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
此输出持续 36 秒,直到您可以看到内存的微小变化。从70,43 到70,53。
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0,00 99,80 70,43 4,81 96,85 90,10 5 0,037 0 0,000 0,037
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0,00 99,80 70,53 4,81 96,85 90,10 5 0,037 0 0,000 0,037
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0,00 99,80 70,53 4,81 96,85 90,10 5 0,037 0 0,000 0,037
因此这个小改动是tomcat的后台进程唯一负责的事情。
PS:您也可以不时使用Memory Analyser 并获取堆转储,您将看到byte[] 数组的已用内存量增加,因为RMI 网络流量。