Permgen空间的这种行为的解释

时间:2013-08-23 13:02:57

标签: java tomcat memory jvm permgen

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

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

这里有奇怪的行为:

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

当我重新部署第二个应用程序时也一样。

然后我尝试同时重新部署两个(tomcat按顺序执行),并且梯子的“步骤”的大小更大,但行为与单个部署中的行为相同。

然后我做了最后一次测试。我同时重新部署了这两个应用程序,直到内存非常接近极限,然后我只重新部署了其中一个应用程序。并且......瞧瞧:PermGen ERROR。

那么......到底发生了什么事?

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

enter image description here

谢谢!

1 个答案:

答案 0 :(得分:1)

OP在这里。

我一直在研究这个问题,我的结论是,或多或少不可能完全理解与permgen空间相关的JVM行为:)

此时我们都已经阅读了一些与类加载器相关的可能内存泄漏的主题。类的定义保持未使用状态,但存储在内存中,直到超出permgen限制。这是理论。但是真的很难知道这个泄漏的起源,我的意思是如果我们的应用程序因为编程错误而导致内存泄漏。

所以最后我解决这个问题的方法是增加内存大小并使用一些标志。这是我在这里的一些相关主题中读到的,在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垃圾收集器来生成java堆的终身

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