22

我们有一个使用 Spring-Hibernate 将注册用户数据持久保存在 Oracle 数据库中的 Web 应用程序。该应用程序在开发环境中运行良好,但是当我们将它复制到具有更多数据的实时环境时,它失败了。最初应用程序正常启动,但经过几次操作后出现“PermGen 空间不足”异常。

我已经开始在 Google、Spring 和 Hibernate 论坛中搜索,但没有帮助。关于这个错误有很多讨论,但是对于每个解决方案,都有人说:“它有效”而其他人说“它不起作用”。

例如,许多人提出增加-XX:MaxPermSizeJVM参数,其他人说它不起作用。有帖子说需要使用javassist库和其他库以及cglib库的使用问题。其他人说问题出在cglib中。

我们使用 Java1.5_0_09、带有 javaassist3.4.GA 的 Spring 2.5、Tomcat 5.5 作为 Web 容器和 Oracle 10g 作为数据库。

谁能解释一下导致这个问题的原因以及如何解决它?

4

8 回答 8

19

-XX:MaxPermSize确实有效,你只需要获得正确的价值。我相信,客户端模式 VM 的默认值为 32mb,服务器模式 VM 的默认值为 64mb。如果你有内存,我建议将其设置为 256mb:

java -XX:MaxPermSize=256m

出现这个问题是因为 Spring 和 Hibernate 可以大量使用运行时生成的类,有时会大量使用。这些生成的类都进入 PermGen 内存池,因此如果您使用这些框架,您通常需要将您的 PermGen 提升到大量。

于 2009-07-14T08:30:24.303 回答
8

You must be aware that some versions of Tomcat have memory leaks on war redeployment. It happened to me on tomcat 6.0.x.

As suggested increase the MaxPermSize, this is a temporary solution for your development machine - and when you get the error, after 2-3 days, just restart the server. On production is not that simple. So this works for development, but this approach doesn't work for production, where you should have the memory leaks issues fixed.

To discover the leaks use the jconsole application that comes with jdk 1.6 and 1.5. You can bind to a process, and watch memory used over time.

You can also read these:

于 2009-07-14T09:09:57.423 回答
4

我已经在 Hibernate 中看到了这个问题(在没有 Spring 的情况下使用)。问题在于我们为每个用户请求创建了一个SessionFactory的实例,而不是为应用程序的生命周期创建一个实例。

我使用YourKit 分析器对此进行了调查并发现了问题。

于 2009-07-14T08:39:57.390 回答
3

正如 skaffman 所说,-XX:MaxPermSize 属性确实有效,但是有时您可能会遇到一个潜在的问题,即提高限制可能只会推迟。

你见过这张纸条吗?它曾经帮助我解决了类似的问题。总结一下链接:

  • 将 JDBC 驱动程序放在 common/lib 中(如tomcat 文档所述)而不是 WEB-INF/lib
  • 不要将 commons-logging 放入 WEB-INF/lib 因为 tomcat 已经引导它
于 2009-07-14T08:35:55.027 回答
2

Visual GC,现在是 JDK 6 的一部分,实时提供了非常好的内存图形表示。您可以看到伊甸园、世代和烫发空间发生了什么。你只是不会明白为什么。

更新:它是我的 JDK 1.6.0_13 发行版中的 bin/jvisualvm.exe。给它你要监控的进程的PID。

于 2009-07-14T09:46:54.277 回答
0

这里的所有响应都与由于 web 应用程序的多次重启而发生的 PermGen 问题有关,但在这种情况下,问题已经发生在 tomcat 重启后的第一次部署时,所以它不可能是 ClassLoader 的引用或公共日志记录的问题。

于 2009-07-14T11:01:20.117 回答
0

如果您在 jdk6 上运行,那么您可以使用 jconsole 应用程序来监控应用程序的内存使用情况并进一步调查。

另一种追求的途径是使用分析器,我使用 JProfiler,并用它来查看应用程序。它会告诉你问题出在哪里。

于 2009-07-14T14:31:53.643 回答
0

我遇到了同样的问题,并且我读到Tomcat 是这种情况的罪魁祸首。

然后我改用码头,一切都很好,应用程序按预期部署/运行。所以如果tomcat不是必须的,那么我建议Jetty。

于 2011-10-04T11:49:38.013 回答