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 本身。
要查看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 网络流量。
【讨论】:
感谢您的回答。这不是让我奖励你全部 500 我猜是因为赏金时间已经结束。我认为它不会有所不同以上是关于Tomcat内存增长的主要内容,如果未能解决你的问题,请参考以下文章