java.lang.OutOfMemoryError:Jetty 的 PermGen 空间错误

Posted

技术标签:

【中文标题】java.lang.OutOfMemoryError:Jetty 的 PermGen 空间错误【英文标题】:java.lang.OutOfMemoryError: PermGen space error with Jetty 【发布时间】:2015-03-15 08:39:37 【问题描述】:

我目前收到java.lang.OutOfMemoryError: PermGen space。我正在使用 Jetty 和 Linux Ubuntu。我已经尝试阅读并尝试之前类似问题中提供的不同解决方案,但我没有任何成功。一个类似的问题是

Dealing with “java.lang.OutOfMemoryError: PermGen space” error

但这些解决方案似乎使用的是 Tomcat 而不是 Jetty。如果我多次重新部署我的服务,我会不断收到内存不足错误。例如,为了测试这一点,我将转到我的 webapps 文件夹并运行 touch *.xml 以更新时间戳,然后重新运行 jetty,我得到内存不足错误。在我的码头文件夹(包括 bin、doc 等、lib、日志、模块、start.jar 的文件夹)我正在运行

java -jar ../start.jar

但这给了我错误。然后我尝试了我在其他示例中阅读的内容,例如:

java -jar ../start.jar JAVA_OPTS="-Xms256m -Xmx512m -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled"

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

-XX:MaxPermSize=128m

然后当我转到 Firefox 并导航到 localhost:8080 并刷新时,在终端中我不断收到错误

java.lang.OutOfMemoryError: PermGen space

【问题讨论】:

【参考方案1】:

您可以在 Jetty 主文件夹的 start.ini 文件中添加这些参数。如果这不起作用,您可以尝试设置更高的 MaxPermSize,例如 1024m。

【讨论】:

【参考方案2】:

除了将 MaxPermSize 提高到更高的值(例如 1024m)之外,您无能为力:

-XX:MaxPermSize=1024m

这是一个常见问题,在Jetty Documentation - Prevent Memory Leaks部分也有说明:

Permgen 问题

Jetty 中的 JSP 引擎是 Jasper。这最初是在 Apache Tomcat 项目,但随着时间的推移已经被许多人分叉 不同的项目。最多 6 个的所有 jetty 版本都使用基于 Apache Jasper 独占,Jetty 6 仅将 Apache Jasper 用于 JSP2.0。 随着 JSP 2.1 的出现,Jetty 6 从 Sun 的 Glassfish 项目,现在是参考实现。

Jasper 的所有分支都存在一个问题,即 permgen 空间 可以通过使用 jsp 标记文件来承受压力。这是因为 jsp实现的类加载架构。每个jsp文件 被有效地编译并且它的类被加载到它自己的类加载器中,所以 以允许热更换。每个 jsp 都包含对 如有必要,标签文件将编译标签,然后使用 它自己的类加载器。如果你有很多引用同一个标签的 jsps 文件,然后标签的类将一遍又一遍地加载到 permgen空间,每个jsp一次。 相关 Glassfish 错误报告是 bug # 3963,等效的 Apache Tomcat 错误报告是 bug # 43878。 Apache Tomcat 项目已经关闭了这个错误报告,状态为 WON'T FIX,但是 Glassfish 的人仍然有这个错误 报告打开并已安排修复。当修复变为 可用,Jetty 项目将把它捡起来并合并到我们的 发布程序

【讨论】:

【参考方案3】:

在 Jetty 9.2+ 中

在你的$jetty.base目录下,添加jvm模块+默认配置

[user]$ cd mybase
[mybase]$ java -jar /path/to/jetty-distribution/start.jar --add-to-start=jvm
INFO: jvm             initialised in $jetty.base/start.ini (appended)
[mybase]$ 

现在去编辑你的$jetty.base/start.ini并配置属性,取消注释那些你想要的东西(不要伪造取消注释--exec)码头在启动时使用。

例子:

# --------------------------------------- 
# Module: jvm
--module=jvm
## JVM Configuration
## If JVM args are include in an ini file then --exec is needed
## to start a new JVM from start.jar with the extra args.
##
## If you wish to avoid an extra JVM running, place JVM args
## on the normal command line and do not use --exec
--exec
-Xmx1024m
-Xmn512m
-XX:MaxPermSize=128m
# -XX:+UseConcMarkSweepGC
# -XX:ParallelCMSThreads=2
# -XX:+CMSClassUnloadingEnabled
# -XX:+UseCMSCompactAtFullCollection
# -XX:CMSInitiatingOccupancyFraction=80
# -verbose:gc
# -XX:+PrintGCDateStamps
# -XX:+PrintGCTimeStamps
# -XX:+PrintGCDetails
# -XX:+PrintTenuringDistribution
# -XX:+PrintCommandLineFlags
# -XX:+DisableExplicitGC
# -Dorg.apache.jasper.compiler.disablejsr199=true

【讨论】:

【参考方案4】:

希望您只需使用我的ClassLoader Leak Prevention library 就能解决这些问题。在您自己的代码和第三方库中,有很多不同的错误会导致此类内存泄漏。有关该问题的更多信息、如何追踪它以及已知的罪犯,可以在this blog series of mine 中找到。特别注意 Jetty 本身中的 this bug 可能会导致某些版本的此类泄漏。

【讨论】:

【参考方案5】:

这是一个较老的问题,但这解决了我的问题:

contextHandler.setInitParameter("org.eclipse.jetty.servlet.Default.useFileMappedBuffer", "false");

【讨论】:

以上是关于java.lang.OutOfMemoryError:Jetty 的 PermGen 空间错误的主要内容,如果未能解决你的问题,请参考以下文章