我有两个不同的服务器上的两个不同的tomcat 7实例(oracle jdk7),硬件configuration几乎相同(均大于24 GB RAM)。 两个tomcat服务器都具有相同的configuration,并在这些服务器上部署相同的Web应用程序。 卡塔利娜select如下:
-XX:PermSize=128m -XX:MaxPermSize=512M -Xmx2048m -XX:+CMSIncrementalMode -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC
在运行负载testing(强调大量并行执行的请求的REST API)时,其中一个服务器会抛出java.lang.OutOfMemoryError: Java heap space (这里是stacktrace: http : //pastebin.com/wuS1MVCC ),另一个服务器工作得很好。 我不知道为什么会这样。 有没有人遇到类似的问题?
所以发生的事情是你的一个Tomcat JVM试图超过你分配给它的2048MB堆。
这听起来像你正在寻找一个特定的答案,像一个检查清单的东西要试,所以在这里你去:
用完堆不是因为内存泄漏,每次请求都会泄漏一点点,或者在负载情况下,可能是因为您只是在JVM上投入的资源比它能处理的多。 你想确定哪些是问题,所以首先看看你如何产生你的负载。
如果问题只发生在高水平的并行请求上,但从未处于较低的水平,那么就有一个问题,即处理每个请求所需内存的请求数量太大。 您可能需要使每个请求使用较less的内存,或者以某种方式限制并发。
如果在处理了一定数量的请求之后发生问题而不pipe并发性如何,那么你就有内存泄漏。 你需要find它并回收内存。
在任何一种情况下,你都将得到一个很好的堆内存分析器的帮助。 有像YourKit Java Profiler这样的商业软件,或者像Eclipse Memory Analyzer这样的免费软件。 find一个适合你的工具,并学习如何使用它来看看什么是记忆。 请注意,您不一定需要使用该工具来启动程序 – 如果您正在服务器上运行负载testing,则可以使用JDK中的jmap命令行工具来捕获文件中的堆转储,然后使用你的工具来分析转储文件。 该工具将告诉你什么对象正在占用你的堆空间。
这两个系统之间有些不同,否则行为就不会有所不同。 请注意,在GC中花费太多的时间太less的结果也会导致错误。 靠近堆的极限运行使GC有这种types的问题。
GC时间过长和OutOfMemory错误
如果在垃圾收集中花费了太多时间,并发收集器将抛出一个OutOfMemoryError:如果超过总时间的98%用于垃圾收集,并且小于2%的堆被恢复,则将抛出OutOfMemoryError。 此function旨在防止应用程序长时间运行,而由于堆太小,进行很less或没有进度。 如有必要,可以通过在命令行中添加-XX:-UseGCOverheadLimit选项来禁用此function。