代码之家  ›  专栏  ›  技术社区  ›  rd22

将战争从Jenkins部署到Tomcat时发生OutOfMemoryError

  •  2
  • rd22  · 技术社区  · 10 年前

    我使用以下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命令有问题,还是由于内存泄漏?我引入了睡眠,以便为应用程序取消部署留出一些时间。我从未尝试过延长睡眠时间。

    谢谢

    1 回复  |  直到 10 年前
        1
  •  3
  •   Zielu    10 年前

    异常表明您的问题来自于填充PermGen空间。它是内存的一部分,Java在其中存储关于类的元数据(比如说加载的类的代码)。当您部署新的web应用程序时,您可以添加新的类并增加PermGen的负载。更糟糕的是,当您在90%的情况下重新部署同一个应用程序时,使用的类的先前版本将保留在内存中,因此您不会从PermGen释放“旧”内存,而只是将其添加到内存中(90%的估计来自于使用DataBase驱动程序、使用ThreadLocal、Scheduler线程的框架……实际上,这几乎总是发生)。

    默认的排列太小(比如64M或类似的荒谬)。使用更高的值启动tomcat,您可以通过向tomcat传递JVM选项来实现,例如:

    JAVA_OPTS=-XX:MaxPermSize=512m-Xmx4024m

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

    您可以在启动tomcat之前设置此变量,或者(我更喜欢这样,您可以修改/bin/catalina脚本以始终在那里设置它们,这样,如果再次启动tomcat,您就不会“忘记”它们)。

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