Tomcat内存越来越大

问题描述 投票:11回答:5

导致tomcat内存增长和下降的原因

java apache tomcat
5个回答
5
投票

它是jconsole本身导致锯齿形图案。

要查看jconsolejvisualvm的效果,您可以编写一个只有主循环的简单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.bat

现在打开jconsole

jconsole <PID>

并一次又一次地执行qazxsw poi命令。您将看到伊甸园空间不断增长,直到达到最大值并且它被垃圾收集。

这是我以1秒的间隔输出的jstat。专注于伊甸园空间jstat --gcutil <PID>

E

正如你所看到的......在连接到进程的jconsole之后,eden空间会逐渐增长并生长,直到它被垃圾收集。这导致锯齿形图案。这是 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 的快照。

jvisualvm

当您对tomcat进程执行相同操作时,您将发现类似的行为。唯一不同的是,即使没有连接jconsole,伊甸园空间也会略微增长。但这种轻微的增长并不是你所看到的锯齿形图案的原因。

这是我的tomcat的enter image description here输出。

jstat

此输出持续36秒,直到您可以看到小内存更改。从 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

因此,这个小小的改变是tomcat的后台进程唯一负责的事情。

PS:您还可以使用 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 并不时获取堆转储,您会看到由于RMI网络流量,Memory Analyser阵列的已用内存量会增加。


3
投票

以下是了解链接答案中解释的锯齿形图案的重要观点:

  • 当收集器运行它时,首先尝试部分收集只释放最近分配的内存
  • 最近创建的仍处于活动状态的对象获得“提升”
  • 一旦对象被提升了几次,即使它已准备好收集,也不会再被部分集合清理掉
  • 这些被称为tenured的对象只有在需要完整集合时才会被清理,以便为程序提供足够的空间来继续运行

问题:即使应用程序完全空闲,导致内存增长的原因是什么?

答:有自动化,计时器等内部预定作业或某些外部进程监视,当应用程序空闲时会导致内存增长。也许您的应用程序具有相同数量的对象,但有些可能更大。例如,你可能有一些byte[]和一些ArryList不断增长缓存。

Sources:


2
投票

Memory leaking without objects growing in number or size首先,这是一个关于“使用5.0 Java TM虚拟机调整垃圾收集”的有用链接

这听起来像GC暂停使tomcat没有响应。开始的一件事是“低暂停”垃圾收集器,带有选项-XX:+ UseConcMarkSweepGC。


1
投票

让我们看看图表在大约12:08,工作记忆的大小是最大的(199 MB)。

大约12点09分,垃圾收集器工作,收集死对象,工作内存大小约为145 MB。

在大约12:12,工作内存增加,生成许多死对象,内存从145 MB增加 - > 155 MB - > 165 MB - > 180 MB - > ... - > 190 MB。

大约12:13,垃圾收集器再次工作,收集死对象,工作内存大小约为145 MB。

...等等。实际上,如果没有特殊事件发生,它是一个周期图。


1
投票

原因可能是多种多样的,没有关于你的应用程序的更多信息:假设它没有自己执行任何重复任务,一个可能的原因可能是JConsole本身,因为收集信息并通过RMI发送它消耗可以从Eden快速收集的内存空间。

您可以通过使用较少“侵入性”工具进行性能分析(例如使用http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html启用GC详细输出)并在类似设置中比较内存使用情况配置文件来测试此假设。

正如其他答案所强调的那样,Tomcat也有自己的开销。您可以通过提供“hello,world”servlet并将两者的内存消耗与类似工具进行比较来测试这个其他假设。

© www.soinside.com 2019 - 2024. All rights reserved.