Tomcat内存增长

Posted

技术标签:

【中文标题】Tomcat内存增长【英文标题】:Tomcat memory growing 【发布时间】:2018-07-22 15:02:47 【问题描述】:

是什么导致tomcat内存增长和下降

【问题讨论】:

由于内存清空成功,这是正常的。 Tomcat 显然有在后台运行的周期性任务,这些任务创建对象并因此分配内存。您可以做的是通过 VisualVM 或其他分析器工具监视应用程序,以确定定期创建的对象或查看源代码。 你用的是哪个版本的jvm和tomcat?您是否尝试过全新的 tomcat 安装? @MehmetSunkur 尝试使用 Java 7 和 tomcat 5.5 以及 java 8 和 tomcat 8.5 这是一个有趣的问题。显然这不是内存泄漏(因为内存通过 GC 返回)。正如你所说的“如果我要给 JVM 更多的内存,比如 12gb,那么 zig zag 模式会从 500mb 变为 3GB”,我想这是因为 GC 是礼貌的,如果不需要,它不想打扰 JVM。但是tomcat在空闲时间做什么会很高兴知道。您是否尝试将您的问题转发给 tomcat 团队? 【参考方案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。

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

【讨论】:

您可以在javaworld.com/article/2073905/build-ci-sdlc/… 阅读更多内容,参见图 7 知道是什么导致内存在不使用应用程序的情况下增长吗?是jvm还是tomcat? 当我没有运行任何 Web 应用程序时,我检查了 Apache Tomcat。它仍然增加,然后减少,然后增加内存......垃圾收集器循环正在工作。 Tomcat只是Java应用的一个例子,你可以使用其他Java应用。【参考方案2】:

以下是了解链接答案中解释的锯齿形模式的要点:

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

问题:是什么导致即使应用程序完全空闲,内存也会如此增长?

答案: 有内部计划作业,如 自动化计时器 等,或一些外部进程监控导致内存增长该应用程序处于空闲状态。也许您的应用程序具有相同数量的对象,但有些可能更大。例如,您可能有一些 ArryList 和一些 StrigBuilder 会不断增长缓存。

来源:

Does this memory usage pattern indicate that my Java application leaks memory? Memory leaking without objects growing in number or size

【讨论】:

首先是什么导致内存增长,你知道吗?【参考方案3】:

http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html 首先,这里有一个有用的链接“使用 5.0 Java TM 虚拟机调整垃圾收集”

这听起来确实像 GC 暂停使 tomcat 无响应。一开始是使用选项 -XX:+UseConcMarkSweepGC 的“低暂停”垃圾收集器。

【讨论】:

【参考方案4】:

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

您可以通过使用较少“侵入性” 的工具(例如使用-verbosegc 启用 GC 详细输出)并比较类似设置中的内存使用情况来测试此假设。

正如其他答案中强调的那样,Tomcat 也可以有自己的开销。您可以通过提供 "hello, world" servlet 并使用类似工具比较两者的内存消耗来测试其他假设。

【讨论】:

【参考方案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 的命令以特定时间间隔重新运行该命令。见watch.bat

现在打开jconsole

jconsole <PID>

并一次又一次地执行jstat 命令。您会看到伊甸园空间不断增长,直到达到最大值并被垃圾回收。

这是jstat --gcutil &lt;PID&gt; 的输出,间隔为 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,4370,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 网络流量。

【讨论】:

感谢您的回答。这不是让我奖励你全部 500 我猜是因为赏金时间已经结束。我认为它不会有所不同

以上是关于Tomcat内存增长的主要内容,如果未能解决你的问题,请参考以下文章

Tomcat内存越来越大

利用jvisualvm工具查找tomcat假死问题

tomcat的内存如何限制大小

关于tomcat内存设置

如何更改tomcat7及以上版本内存设置

如何更改tomcat7及以上版本内存设置