是什么原因导致Tomcat内存增长和下降
是什么原因导致Tomcat内存增长和下降
它是jconsole本身导致了这种波浪形状。
为了看到或的效果,您可以编写一个简单的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
关注 eden 空间 E
。该值为空间当前容量的百分比。详见 jstat。
如果您反复执行该命令,则会发现 eden 空间利用率不会增长。它将保持在例如 69,34
。我在 Windows 上使用类似 Linux watch 的命令以特定间隔重新运行命令。请参见 watch.bat。
现在打开 jconsole
。
jconsole <PID>
执行jstat
命令,反复执行。您会看到伊甸园空间不断增长,直到达到最大值并进行垃圾回收。
这是我每隔1秒钟输出的jstat --gcutil <PID>
结果。请关注伊甸园空间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
的快照。
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
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后台进程唯一需要负责的事情。
附注: 您也可以使用Memory Analyser不时地获取堆转储,您会发现byte[]
数组的使用内存量增加,因为RMI网络流量。
ArryList
和一些StrigBuilder
,它们不断增加缓存。
http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html
首先,这是一篇关于“使用Java TM虚拟机5.0调整垃圾回收”的有用链接。
听起来像是GC暂停导致了Tomcat无响应。一种解决方法是使用"-XX:+UseConcMarkSweepGC"选项使用低暂停垃圾收集器。
原因可能各不相同,如果没有更多关于您的应用程序的信息:假设它没有自己执行任何重复任务,则可能的原因之一是JConsole本身,因为收集信息并通过RMI发送它会消耗内存,这些内存可以从Eden空间中快速收集。
您可以通过使用较少"侵入性"的工具(例如使用-verbosegc
启用GC详细输出)进行分析,并在类似设置中比较内存使用情况来测试此假设。
正如其他答案所强调的那样,Tomcat也可能有其自己的开销。您可以通过提供一个"hello, world" servlet并使用类似的工具比较两者的内存消耗来测试这个假设。