2

我正在尝试在一个项目中相互协作的 2 个独立的网络应用程序的一些问题。在 X 次部署之后,我得到了臭名昭著的“java.lang.OutOfMemoryError: PermGen space”错误。

所以我一直在用 VisualVM 监控 PermGen 空间,不断地重新部署应用程序,看看发生了什么。

这里有奇怪的行为:

首先,我重新部署了第一个应用程序超过 15 次。行为与预期一致:内存图就像一个不断增加的阶梯,直到接近最大大小(67MB)。在这一点上,内存被释放并返回到初始级别。

当我重新部署第二个应用程序时也是如此。

然后我尝试同时重新部署两者(tomcat 依次执行此操作),并且梯子的“台阶”的大小更大,但行为与单个部署相同。

然后我完成了最后一个测试。我同时重新部署了两个应用程序,直到内存非常接近极限,然后我只重新部署了一个应用程序。而且.. 瞧:PermGen 错误。

所以..这里到底发生了什么?

VisualVM的示意图。前半部分(左)对应于单个部署(应用程序 1 和 2)。后半部分(右)代表我超出限制并得到错误的点。

在此处输入图像描述

谢谢!

4

1 回答 1

1

在这里。

我一直在对此进行一些研究,我的结论是,要完全理解与 permgen 空间相关的 JVM 行为或多或少是不可能的 :)

至此,我们都已经阅读了一些与类加载器相关的可能内存泄漏的主题。类的定义保持未使用,但存储在内存中,直到超过 permgen-limit。那是理论。但是很难真正了解这种泄漏的起源,我的意思是我们的应用程序中是否存在由于不良编程引起的内存泄漏。

所以最后我对这个问题的解决方案是增加内存大小并使用一些标志。这是我在 stackoverflow 中的一些相关主题中读到的内容。这是用户在发现 permgen 错误时常用的操作。我不确定这是否是一种解决方案,或者仅仅是一种忘记这种痛苦的方法......;)

在 Catalina.sh (TOMCAT) 中,我添加了这一行:

export CATALINA_OPTS="-Xms64m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled"

在哪里:

-Xms64m将 Java 堆内存的最小大小设置为 64MB。

-Xmx512m将 Java 堆内存的最大大小设置为 512MB。

-XX:PermSize=128m将 permgen 内存的初始大小设置为 128MB。

-XX:MaxPermSize=512m将 permgen 内存的最大大小设置为 512MB。

-XX:+UseConcMarkSweepGC : jvm 将使用 Concurrent Mark Sweep Garbage Collector 进行 java heap 的tenured generation

-XX:+CMSClassUnloadingEnabled:垃圾收集器将清除 PermGen 并删除不再使用的类。

于 2013-08-26T08:26:07.117 回答