将 war 从 Jenkins 部署到 Tomcat 时出现 OutOfMemoryError

OutOfMemoryError while deploying a war from Jenkins to Tomcat

我使用以下 shell 命令从 Jenkins 部署我的应用程序:

rm -rf E:/FooTomcat/apache-tomcat-7.0.55/webapps/foo-web;
rm -rf E:/FooTomcat/apache-tomcat-7.0.55/webapps/foo-web.war;
sleep 2;
cp foo-web/target/foo-web-0.0.1-SNAPSHOT.war E:/FooTomcat/apache-tomcat-7.0.55/webapps/foo-web.war

经常在开始定期构建时 Tomcat 内存不足并出现以下错误。

Feb 13, 2015 3:59:58 PM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive E:\FooTomcat\apache-tomcat-7.0.55\webapps\foo-web.war
Feb 13, 2015 4:00:06 PM org.apache.catalina.startup.HostConfig deployWARs
SEVERE: Error waiting for multi-thread deployment of WAR files to complete
java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: PermGen space
    at java.util.concurrent.FutureTask.report(FutureTask.java:122)
    at java.util.concurrent.FutureTask.get(FutureTask.java:188)
    at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:818)
    at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:488)
    at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1658)

我有一个 windows 环境并通过 cygwin 执行 shell。

shell 命令有问题,还是由于内存泄漏?我引入睡眠是为了给应用程序一些时间来取消部署。我从来没有尝试过增加睡眠时间。

谢谢。

因为异常表明您的问题来自填充 PermGen space。它是内存的一部分,Java 存储关于您的 类 的元数据(假设您加载的 类 的代码)。当您部署新的网络应用程序时,您会添加新的 类 并增加 PermGen 的负载。更糟糕的是,当您在 90% 的情况下重新部署相同的应用程序时,使用的 类 的先前版本保留在内存中,因此您不会从 PermGen 释放 'old' 内存,而只是添加到它(90% 的估计来自使用数据库驱动程序,使用 ThreadLocal 的框架,调度程序线程......实际上它几乎一直发生)。

默认的 permgen 太小(比如 64M 或其他荒谬的东西)。以更高的值开始 tomcat,您可以通过将 JVM 选项传递给 tomcat 来实现,例如:

JAVA_OPTS = -XX:MaxPermSize=512m -Xmx4024m

(首先将 perm 大小设置为 512MB,然后将堆大小设置为 4G,这对于现代系统来说很好)。

你在开始之前设置这个变量 tomcat,或者(我更喜欢这样,你可以修改你的 /bin/catalina 脚本以始终在那里设置它们,这样你就不会 'forget' 如果你再次开始你的 tomcat 他们。

从 tomact 7 开始,当您取消部署应用程序时,tomcat 日志会显示应用程序在内存中的警告(并填满您的 PermGen),您可能需要检查它们并尝试修复一些问题(更新框架,正确关闭线程池...)