处理" java.lang.OutOfMemoryError:PermGen空间"错误

时间:2020-03-06 14:19:10  来源:igfitidea点击:

最近,我在Web应用程序中遇到了此错误:

java.lang.OutOfMemoryError: PermGen space

这是在Tomcat 6和JDK 1.6上运行的典型Hibernate / JPA + IceFaces / JSF应用程序。
显然,这可能是在重新部署应用程序几次之后发生的。

是什么原因造成的,可以采取什么措施避免发生这种情况?
我该如何解决该问题?

解决方案

解决方案是在启动Tomcat时将这些标志添加到JVM命令行:

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

我们可以通过关闭tomcat服务,然后进入Tomcat / bin目录并运行tomcat6w.exe来做到这一点。在" Java"选项卡下,将参数添加到" Java选项"框中。单击"确定",然后重新启动服务。

如果出现错误,则指定的服务不存在为已安装的服务,应运行:

tomcat6w //ES//servicename

其中servicename是在services.msc中查看的服务器的名称

资料来源:orx对Eric的《敏捷答案》的评论。

另外,我们可以切换到JRockit,后者对permgen的处理方式与sun的jvm不同。通常它也具有更好的性能。

http://www.oracle.com/technetwork/middleware/jrockit/overview/index.html

jrockit也为我解决了这个问题;但是,我注意到servlet的重新启动时间要差得多,因此虽然在生产中更好,但在开发中却有点拖累。

对于Sun JVM,使用命令行参数-XX:MaxPermSize = 128m(显然,将128替换为所需的任何大小)。

多次部署后发生的应用程序服务器PermGen错误很可能是由容器保存到旧应用程序的类加载器中的引用引起的。例如,使用自定义日志级别的类将导致引用由应用服务器的类加载器保留。我们可以使用现代(JDK6 +)JVM分析工具(例如jmap和jhat)来检测这些类加载器之间的泄漏,以查看哪些类继续保留在应用程序中,然后重新设计或者取消使用它们。通常的可疑对象是数据库,记录器和其他基础框架级别的库。

请参阅Classloader泄漏:可怕的" java.lang.OutOfMemoryError:PermGen空间"异常,尤其是其后续文章。

尝试-XX:MaxPermSize = 256m,如果仍然存在,请尝试-XX:MaxPermSize = 512m

内存的配置取决于应用程序的性质。

你在做什么?

进行多少笔交易?

我们正在加载多少数据?

等等。

等等。

等等

可能我们可以分析应用程序并开始清除应用程序中的某些模块。

Apparently this can occur after redeploying an application a few times

Tomcat具有热部署功能,但是会占用内存。尝试不时重新启动容器。另外,我们将需要知道在生产模式下运行所需的内存量,这对于该研究而言似乎是个好时机。

我们最好尝试使用-XX:MaxPermSize = 128M,而不要使用-XX:MaxPermGen = 128M。

我无法告诉我们该内存池的确切用途,但它与装入JVM的类数有关。 (因此,为tomcat启用类卸载可以解决该问题。)如果应用程序在运行时生成并编译类,则很有可能需要比默认更大的内存池。

我结合使用了Hibernate + Eclipse RCP,尝试使用-XX:MaxPermSize = 512m和-XX:PermSize = 512m,这似乎对我有用。

设置-XX:PermSize = 64m -XX:MaxPermSize = 128m以后我们也可以尝试增加MaxPermSize。希望它能工作。同样对我有用。仅设置MaxPermSize对我不起作用。

他们说Tomcat的最新版本(6.0.28或者6.0.29)可以更好地重新部署servlet。

"它们"是错误的,因为我正在运行6.0.29,即使在设置所有选项后也遇到相同的问题。正如蒂姆·霍兰德(Tim Howland)上文所述,这些选择只会推迟不可避免的事情。它们使我在遇到错误之前重新部署了3次,而不是每次重新部署。

如果我们在eclipse IDE中获得了此功能,即使在设置了参数之后
--launcher.XXMaxPermSize`,-XX:MaxPermSize等,但是如果仍然遇到相同的错误,则极有可能是日食使用的是错误的JRE版本,该版本的JRE已由某些第三方应用程序安装并设置为默认值。这些错误的版本不会选择PermSize参数,因此,无论我们进行了什么设置,我们仍然会不断遇到这些内存错误。因此,在eclipse.ini中添加以下参数:

-vm <path to the right JRE directory>/<name of javaw executable>

还要确保在Eclipse的首选项中将默认JRE设置为Java的正确版本。

对我有用的唯一方法是使用JRockit JVM。我有MyEclipse 8.6.

JVM的堆存储由运行中的Java程序生成的所有对象。 Java使用" new"运算符创建对象,并在运行时在堆上分配用于新对象的内存。垃圾回收是一种自动释放程序不再引用的对象所包含的内存的机制。

我遇到了我们在这里讨论的问题,我的场景是eclipse-helios + tomcat + jsf,而我们正在做的就是将一个简单的应用程序部署到tomcat。我在这里显示了相同的问题,如下解决。

在eclipse中,转到server选项卡,在我的案例tomcat 7.0中双击已注册的服务器,它会打开我的文件服务器的常规注册信息。在"常规信息"部分,单击链接"打开启动配置",这将打开在这两个条目末尾添加的VM参数中"参数"选项卡中服务器选项的执行。

-XX: MaxPermSize = 512m
-XX: PermSize = 512m

准备好了