【问题标题】:Dealing with "java.lang.OutOfMemoryError: PermGen space" error处理“java.lang.OutOfMemoryError: PermGen space”错误
【发布时间】:2010-09-10 10:26:46
【问题描述】:

最近我在我的网络应用程序中遇到了这个错误:

java.lang.OutOfMemoryError: PermGen 空间

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

是什么原因造成的,可以采取什么措施来避免它? 我该如何解决这个问题?

【问题讨论】:

  • 我已经为此奋斗了好几个小时,但我没有好消息。请参阅我的相关问题:stackoverflow.com/questions/1996088/… 您可能仍有内存泄漏,例如类没有被垃圾收集,因为您的 WebAppClassLoader 没有被垃圾收集(它有一个未清除的外部引用)。增加 PermGen 只会延迟 OutOfMemoryError,并且允许类垃圾回收是前提条件,但如果类加载器仍有对它的引用,则不会对类进行垃圾回收。
  • 我在添加 display taglib 时遇到此错误。删除so也解决了错误。为什么会这样?
  • 你是怎么遇到的?
  • 使用 JDK 1.8 :þ 欢迎来到 MetaSpace
  • 如果使用 Windows,请遵循这些说明,而不是尝试在配置文件中手动设置标志。这会正确设置注册表中的值,以便 Tomcat 在运行时调用。 stackoverflow.com/questions/21104340/…

标签: exception memory-leaks out-of-memory java-6 permgen


【解决方案1】:

在尝试调试 JBoss 应用程序时,谁在 IntelliJ 中遇到了同样的问题: 我刚刚将此-XX: MaxPermSize = 128m 添加到运行/调试配置中的 VM 选项中。您可以将其增加到 256m 以更有保证地工作。

【讨论】:

    【解决方案2】:

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

    -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled
    

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

    如果您收到错误指定的服务不作为已安装的服务存在,您应该运行:

    tomcat6w //ES//servicename
    

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

    来源:orx对Eric's Agile Answers的评论。

    【讨论】:

    • 下面的文章建议 -XX:+UseConcMarkSweepGC 和 -XX:MaxPermSize=128m 为好。 my.opera.com/karmazilla/blog/2007/03/13/…
    • -XX:+CMSPermGenSweepingEnabled 此选项会降低性能。它使每个请求在我们的系统上花费的时间是平时的三倍。小心使用。
    • 为我工作 - 谢谢 - 我在 Ubuntu 10.10 上使用 Tomcat6 执行此操作 - 我创建了一个新文件:/usr/share/tomcat6/bin/setenv.sh 并在其中添加了以下行: JAVA_OPTS="-Xms256m -Xmx512m -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled" - 重新启动tomcat使用:sudo /etc/init.d/tomcat6 start
    • 在 tomcat 6.0.29 启动时,来自我的 catalina.out 日志文件:“请在未来使用 CMSClassUnloadingEnabled 代替 CMSPermGenSweepingEnabled”
    • 首先,最好解释一下这些标志的真正作用。只是说:“这样做并享受”是不够的恕我直言。
    【解决方案3】:

    Perm gen space 错误是由于使用了大空间而不是 jvm 提供空间来执行代码。

    在 UNIX 操作系统中解决此问题的最佳方法是更改​​ bash 文件的某些配置。以下步骤可解决问题。

    在终端上运行命令gedit .bashrc

    使用以下值创建JAVA_OTPS 变量:

    export JAVA_OPTS="-XX:PermSize=256m -XX:MaxPermSize=512m"
    

    保存 bash 文件。在终端上运行命令 exec bash。重启服务器。

    我希望这种方法可以解决您的问题。如果您使用低于 8 的 Java 版本,有时会出现此问题。但如果您使用 Java 8,则永远不会出现问题。

    【讨论】:

      【解决方案4】:

      java.lang.OutOfMemoryError: PermGen 空间消息表示永久代在内存中的区域已耗尽。

      任何 Java 应用程序都可以使用有限的内存量。您的特定应用程序可以使用的确切内存量在应用程序启动期间指定。

      Java 内存被分成不同的区域,如下图所示:

      元空间:一个新的内存空间诞生了

      JDK 8 HotSpot JVM 现在使用本机内存来表示类元数据,称为 Metaspace;类似于 Oracle JRockit 和 IBM JVM。

      好消息是,这意味着不再有java.lang.OutOfMemoryError: PermGen 空间问题,并且您无需再使用Java_8_Download 或更高版本来调整和监控此内存空间。

      【讨论】:

      • MetaSpace 也可以OutOfMemory
      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

        另外,如果您在 webapp 中使用 log4j,请查看 log4j documentation 中的这一段。

        似乎如果您使用PropertyConfigurator.configureAndWatch("log4j.properties"),当您取消部署您的webapp 时会导致内存泄漏。

        【讨论】:

          【解决方案7】:

          如果有人在 netbeans 中遇到同样的错误,那么这就是我修复它的方法。

          在 Netbeans 中:

          转到服务选项卡-->在服务器上-->选择属性-->转到平台选项卡-->在vm选项中输入-Xms1024m

          就我而言,我给出了 -Xms4096m

          截图如下:

          【讨论】:

            【解决方案8】:

            为 Tomcat 分配更多内存不是正确的解决方案。

            正确的解决方案是在上下文被销毁并重新创建(热部署)后进行清理。解决方案是阻止内存泄漏。

            如果您的 Tomcat/Webapp 服务器告诉您取消注册驱动程序 (JDBC) 失败,请取消注册它们。这将阻止内存泄漏。

            您可以创建一个 ServletContextListener 并在您的 web.xml 中配置它。这是一个示例 ServletContextListener:

            import java.sql.Driver;
            import java.sql.DriverManager;
            import java.sql.SQLException;
            import java.util.Enumeration;
            
            import javax.servlet.ServletContextEvent;
            import javax.servlet.ServletContextListener;
            
            import org.apache.log4j.Logger;
            
            import com.mysql.jdbc.AbandonedConnectionCleanupThread;
            
            /**
             * 
             * @author alejandro.tkachuk / calculistik.com
             *
             */
            public class AppContextListener implements ServletContextListener {
            
                private static final Logger logger = Logger.getLogger(AppContextListener.class);
            
                @Override
                public void contextInitialized(ServletContextEvent arg0) {
                    logger.info("AppContextListener started");
                }
            
                @Override
                public void contextDestroyed(ServletContextEvent arg0) {
                    logger.info("AppContextListener destroyed");
            
                    // manually unregister the JDBC drivers
                    Enumeration<Driver> drivers = DriverManager.getDrivers();
                    while (drivers.hasMoreElements()) {
                        Driver driver = drivers.nextElement();
                        try {
                            DriverManager.deregisterDriver(driver);
                            logger.info(String.format("Unregistering jdbc driver: %s", driver));
                        } catch (SQLException e) {
                            logger.info(String.format("Error unregistering driver %s", driver), e);
                        }
            
                    }
            
                    // manually shutdown clean up threads
                    try {
                        AbandonedConnectionCleanupThread.shutdown();
                        logger.info("Shutting down AbandonedConnectionCleanupThread");
                    } catch (InterruptedException e) {
                        logger.warn("SEVERE problem shutting down AbandonedConnectionCleanupThread: ", e);
                        e.printStackTrace();
                    }        
                }
            }
            

            在这里你可以在你的 web.xml 中配置它:

            <listener>
                <listener-class>
                    com.calculistik.mediweb.context.AppContextListener 
                </listener-class>
            </listener>  
            

            【讨论】:

              【解决方案9】:

              在这种情况下,第一步是检查是否允许 GC 从 PermGen 中卸载类。标准 JVM 在这方面相当保守——类生来就是为了永远存在。所以一旦加载,即使没有代码再使用它们,类也会留在内存中。当应用程序动态创建大量类并且生成的类在较长时间内不需要时,这可能会成为一个问题。在这种情况下,允许 JVM 卸载类定义会很有帮助。这可以通过在启动脚本中添加一个配置参数来实现:

              -XX:+CMSClassUnloadingEnabled
              

              默认情况下,此设置为 false,因此要启用此设置,您需要在 Java 选项中显式设置以下选项。如果启用 CMSClassUnloadingEnabled,GC 也会清除 PermGen 并删除不再使用的类。请记住,此选项仅在使用以下选项启用 UseConcMarkSweepGC 时才有效。因此,在运行 ParallelGC 或(上帝保佑)串行 GC 时,请确保您已通过指定以下方式将 GC 设置为 CMS:

              -XX:+UseConcMarkSweepGC
              

              【讨论】:

                【解决方案10】:

                我遇到了类似的问题。 我的是 JDK 7 + Maven 3.0.2 + Struts 2.0 + Google GUICE 依赖注入的项目。

                每当我尝试运行 mvn clean package 命令时,它都会显示以下错误并发生 “BUILD FAILURE”

                org.apache.maven.surefire.util.SurefireReflectionException: java.lang.reflect.InvocationTargetException;嵌套异常是 java.lang.reflect.InvocationTargetException: null java.lang.reflect.InvocationTargetException 引起:java.lang.OutOfMemoryError: PermGen space

                我尝试了上述所有有用的提示和技巧,但不幸的是,没有一个对我有用。 下面逐步描述了对我有用的方法:=>

                1. 转到您的 pom.xml
                2. 搜索&lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;
                3. 添加一个新的&lt;configuration&gt; 元素,然后添加&lt;argLine&gt; 子元素,其中通过-Xmx512m -XX:MaxPermSize=256m 如下所示 =>

                <configuration> <argLine>-Xmx512m -XX:MaxPermSize=256m</argLine> </configuration>

                希望对您有所帮助,祝您编程愉快:)

                【讨论】:

                  【解决方案11】:

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

                  参见Classloader leaks: the dreaded "java.lang.OutOfMemoryError: PermGen space" exception,尤其是它的followup post

                  【讨论】:

                  • 这只是问题的真正解决方案,在某些情况下很难实现。
                  • 另一个非常好的来源是people.apache.org/~markt/presentations/…(来自 Tomcat 发布管理器!!)。
                  • 虽然理论上这可以回答这个问题,it would be preferable 在这里包含答案的基本部分,并提供链接以供参考。
                  【解决方案12】:

                  1) 增加 PermGen 内存大小

                  可以做的第一件事就是使永久代堆空间的大小更大。这不能使用通常的 –Xms(设置初始堆大小)和 –Xmx(设置最大堆大小)JVM 参数来完成,因为如上所述,永久代堆空间与常规 Java 堆空间完全分开, 这些参数为这个常规的 Java 堆空间设置了空间。但是,可以使用类似的参数(至少对于 Sun/OpenJDK jvms)来增大永久代堆的大小:

                   -XX:MaxPermSize=128m
                  

                  默认为 64m。

                  2) 启用扫描

                  另一种解决问题的方法是允许卸载类,这样你的 PermGen 就永远不会用完:

                  -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled
                  

                  过去,类似的事情对我来说很神奇。不过有一件事,在使用这些时会有一个显着的性能折衷,因为 permgen 扫描会为你提出的每个请求或类似的东西发出额外的 2 个请求。您需要在使用与权衡之间取得平衡。

                  您可以找到此错误的详细信息。

                  http://faisalbhagat.blogspot.com/2014/09/java-outofmemoryerror-permgen.html

                  【讨论】:

                  【解决方案13】:

                  如今最简单的答案是使用 Java 8。

                  它不再专门为 PermGen 空间保留内存,允许 PermGen 内存与常规内存池混合。

                  请记住,如果您不希望 Java 8 抱怨它们没有做任何事情,则必须删除所有非标准的 -XXPermGen...=... JVM 启动参数。

                  【讨论】:

                  • 您好,这个答案已经给出:stackoverflow.com/a/22897121/505893。为了清楚起见,请删除您的答案。如果需要,您可以改进我提到的答案。谢谢;)
                  • @bluish 感谢您指出这一点;但是,在谈论 OutOfMemoryExceptions 和泄漏元数据时,这个答案完全是一边倒的。它也没有提到删除 PermGen 选项的非常重要的点。简而言之,我不确定我会改进答案,而是重写它。如果只是快速润色,我会感到不那么犹豫,但看起来它不仅仅是快速润色,我不想冒犯原作者。尽管如此,这个答案列表还是一团糟,也许最好还是杀掉我的帖子。
                  【解决方案14】:

                  我尝试了几个答案,最终唯一能完成工作的是 pom 中编译器插件的配置:

                  <plugin>
                      <groupId>org.apache.maven.plugins</groupId>
                      <artifactId>maven-compiler-plugin</artifactId>
                      <version>2.3.2</version>
                      <configuration>
                          <fork>true</fork>
                          <meminitial>128m</meminitial>
                          <maxmem>512m</maxmem>
                          <source>1.6</source>
                          <target>1.6</target>
                          <!-- prevent PermGen space out of memory exception -->
                          <!-- <argLine>-Xmx512m -XX:MaxPermSize=512m</argLine> -->
                      </configuration>
                  </plugin>
                  

                  希望这个有帮助。

                  【讨论】:

                  • "argLine" 无法被 maven-compiler-plugin 2.4 识别。它只支持“compilerArgument”,它给出错误:-XX:MaxPermSize=256m [ERROR] 执行 javac 失败,但无法解析错误:javac: invalid flag: -XX:MaxPermSize=256m : javac
                  • 如果您的编译阶段用完了 permgen,请在 maven-compiler-plugin 上设置 。如果单元测试用完了 maven-surefire-plugin 中的 permgen set
                  【解决方案15】:

                  人们常犯的错误是认为堆空间和永久空间是相同的,这根本不是真的。您可能在堆中剩余大量空间,但仍然可能在 permgen 中耗尽内存。

                  PermGen 中 OutofMemory 的常见原因是 ClassLoader。每当一个类被加载到 JVM 中时,它的所有元数据以及 Classloader 都保存在 PermGen 区域中,当加载它们的 Classloader 准备好进行垃圾收集时,它们将被垃圾收集。如果 Classloader 存在内存泄漏,那么它加载的所有类都将保留在内存中,并在您重复几次后导致 permGen 内存不足。经典的例子是Java.lang.OutOfMemoryError:PermGen Space in Tomcat

                  现在有两种方法可以解决这个问题:
                  1.查找Memory Leak的原因或是否有内存泄漏。
                  2. 使用JVM参数-XX:MaxPermSize-XX:PermSize增加PermGen Space的大小。

                  您也可以在 Java 中查看2 Solution of Java.lang.OutOfMemoryError 了解更多详情。

                  【讨论】:

                  • 如何传递参数-XX:MaxPermSize and -XX:PermSize??我找不到catalina.bat。我的tomcat版本是5.5.26
                  • 如何查找类加载器的内存泄漏?你有什么工具推荐吗?
                  • @amit 获取工具建议,请参阅社区 wiki 对此问题的回答。
                  • @Deckard 进入 Tomcat/bin 目录并运行 tomcat6w.exe。在“Java”选项卡下,将参数添加到“Java 选项”框。点击“确定”
                  【解决方案16】:

                  你也可以通过以下方式解决这个问题:

                  rm -rf <tomcat-dir>/work/* <tomcat-dir>/temp/*
                  

                  清除 worktemp 目录可以让 Tomcat 干净启动。

                  【讨论】:

                    【解决方案17】:
                    1. 从 Tomcat 的 bin 目录打开 tomcat7w 或在开始菜单中输入 Monitor Tomcat (打开一个选项卡式窗口,其中包含各种服务信息)。
                    2. 在 Java 选项文本区域中添加这一行:

                      -XX:MaxPermSize=128m
                      
                    3. 将初始内存池设置为 1024(可选)。
                    4. 将最大内存池设置为 1024(可选)。
                    5. 点击确定。
                    6. 重新启动 Tomcat 服务。

                    【讨论】:

                      【解决方案18】:

                      added-XX: MaxPermSize = 128m(你可以试验哪个效果最好)到VM Arguments,因为我正在使用eclipse ide。在大多数 JVM 中,default PermSize 约为 64MB,如果项目中有太多类或大量字符串,则会耗尽内存。

                      对于eclipse,在answer也有描述。

                      步骤 1:在 Servers 选项卡上双击 tomcat 服务器

                      第 2 步打开启动会议并将-XX: MaxPermSize = 128m 添加到现有VM 争论 的末尾。

                      【讨论】:

                      • 感谢您提供最佳详细答案(注意:单击“打开启动配置”以打开“编辑配置”窗口...但我使用了以下参数:“-XX:+CMSClassUnloadingEnabled -XX: +CMSPermGenSweepingEnabled"
                      【解决方案19】:

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

                      在 Eclipse 中转到 servers 选项卡,在我的案例 tomcat 7.0 中双击已注册的服务器,它会打开我的文件服务器的一般注册信息。在 “常规信息” 部分单击链接 “打开启动配置” ,这将在最后添加的 VM 参数中的“参数”选项卡中打开服务器选项的执行这些两个条目

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

                      准备好了。

                      【讨论】:

                        【解决方案20】:

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

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

                        【讨论】:

                          【解决方案21】:

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

                          【讨论】:

                            【解决方案22】:

                            如果您有真正的内存泄漏,增加永久代大小或调整 GC 参数将无济于事。如果您的应用程序或它使用的某个 3rd 方库泄漏类加载器,唯一真正且永久的解决方案是找到此泄漏并修复它。有许多工具可以帮助您,最近的一个是 Plumbr,它刚刚发布了具有所需功能的新版本。

                            【讨论】:

                              【解决方案23】:

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

                              【讨论】:

                              • 如果它仍然存在,请尝试XX:MaxPermSize=1024m :)
                              • 如果它仍然存在,请尝试 XX:MaxPermSize=2048m :)
                              • 如果它仍然存在,请重新考虑您的应用程序!或者试试 XX:MaxPermSize=4096m :)
                              • 你也可以试试 8192m 但这有点矫枉过正
                              • 确实有点矫枉过正 -- 640KB 对于任何人来说都应该足够了!
                              【解决方案24】:

                              或者,您可以切换到 JRockit,它处理 permgen 的方式与 sun 的 jvm 不同。它通常也具有更好的性能。

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

                              【讨论】:

                              • 虽然 JRockit 确实没有 PermGen,但从长远来看这无济于事。你会得到java.lang.OutOfMemoryError: There is insufficient native memory
                              【解决方案25】:

                              在部署和取消部署复杂的 Web 应用程序时,我也一直在努力解决这个问题,并认为我应该添加一个解释和我的解决方案。

                              当我在 Apache Tomcat 上部署应用程序时,会为该应用程序创建一个新的 ClassLoader。然后使用 ClassLoader 加载应用程序的所有类,并且在取消部署时,一切都应该很好地消失。然而,实际上并没有那么简单。

                              在 Web 应用程序的生命周期中创建的一个或多个类包含一个静态引用,该引用沿线某处引用 ClassLoader。由于引用最初是静态的,因此再多的垃圾收集都不会清理此引用 - ClassLoader 以及它加载的所有类都将保留下来。

                              在几次重新部署之后,我们遇到了 OutOfMemoryError。

                              现在这已成为一个相当严重的问题。我可以确保在每次重新部署后重新启动 Tomcat,但这会关闭整个服务器,而不仅仅是重新部署的应用程序,这通常是不可行的。

                              因此,我在代码中组合了一个解决方案,该解决方案适用于 Apache Tomcat 6.0。我没有在任何其他应用程序服务器上进行过测试,并且必须强调如果不修改任何其他应用程序服务器,这很可能无法正常工作

                              我还想说,我个人讨厌这段代码,并且 如果可以将现有代码更改为使用正确的关闭和清理方法,那么任何人都不应该将其用作“快速修复”。唯一应该使用的情况是,如果您的代码依赖于一个外部库(在我的情况下,它是一个 RADIUS 客户端),它不提供清理其自己的静态引用的方法。

                              无论如何,继续使用代码。这应该在应用程序取消部署时调用 - 例如 servlet 的 destroy 方法或(更好的方法)ServletContextListener 的 contextDestroyed 方法。

                              //Get a list of all classes loaded by the current webapp classloader
                              WebappClassLoader classLoader = (WebappClassLoader) getClass().getClassLoader();
                              Field classLoaderClassesField = null;
                              Class clazz = WebappClassLoader.class;
                              while (classLoaderClassesField == null && clazz != null) {
                                  try {
                                      classLoaderClassesField = clazz.getDeclaredField("classes");
                                  } catch (Exception exception) {
                                      //do nothing
                                  }
                                  clazz = clazz.getSuperclass();
                              }
                              classLoaderClassesField.setAccessible(true);
                              
                              List classes = new ArrayList((Vector)classLoaderClassesField.get(classLoader));
                              
                              for (Object o : classes) {
                                  Class c = (Class)o;
                                  //Make sure you identify only the packages that are holding references to the classloader.
                                  //Allowing this code to clear all static references will result in all sorts
                                  //of horrible things (like java segfaulting).
                                  if (c.getName().startsWith("com.whatever")) {
                                      //Kill any static references within all these classes.
                                      for (Field f : c.getDeclaredFields()) {
                                          if (Modifier.isStatic(f.getModifiers())
                                                  && !Modifier.isFinal(f.getModifiers())
                                                  && !f.getType().isPrimitive()) {
                                              try {
                                                  f.setAccessible(true);
                                                  f.set(null, null);
                                              } catch (Exception exception) {
                                                  //Log the exception
                                              }
                                          }
                                      }
                                  }
                              }
                              
                              classes.clear();
                              

                              【讨论】:

                              • 我知道我写这篇文章已经 8 年多了,但从那时到现在,我找到了更深层次的根本原因和解决方案。这是因为虽然 webapp 中的所有类都归上下文类加载器所有,但调用启动和关闭回调的线程归父类加载器所有。这意味着如果关闭代码初始化了一个线程局部变量,这将导致父类加载器最终持有对上下文类加载器的引用,从而阻碍了良好的清理。
                              • 幸运的是,有一个非常简单的修复方法 - 将当前在 shutdown 方法中的所有代码移动到新的 Thread 对象的 run 方法中。然后在shutdown方法中,启动这个线程,等待它完成。清理代码将以相同的方式执行,但任何线程局部变量将保持绑定到上下文类加载器而不是泄漏。
                              【解决方案26】:

                              我遇到了完全相同的问题,但不幸的是,没有一个建议的解决方案真正适合我。部署过程中没有出现问题,我也没有进行任何热部署。

                              在我的情况下,在我的网络应用程序执行期间,每次都在同一时间发生问题,同时连接(通过休眠)到数据库。

                              This link(前面也提到过)确实提供了足够的内部来解决问题。将 jdbc-(mysql)-driver 从 WEB-INF 移到 jre/lib/ext/ 文件夹中似乎已经解决了这个问题。这不是理想的解决方案,因为升级到更新的 JRE 需要您重新安装驱动程序。 另一个可能导致类似问题的候选者是 log4j,因此您可能也想移动它

                              【讨论】:

                              • 如果您不想将驱动程序包含在 jre/lib/ext 中,则可以通过将驱动程序包含在容器启动类路径中来获得相同的结果。 java -cp /path/to/jdbc-mysql-driver.jar:/path/to/container/bootstrap.jar container.Start
                              【解决方案27】:

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

                              【讨论】:

                              • 唯一的问题是你只是在推迟不可避免的事情——在某些时候你也会用完那里的空间。这是一个非常实用的解决方案,但它并不能永久解决。
                              • 同样的事情发生在 Eclipse 和任何时候你有很多动态类加载。类加载器不会被丢弃并永远存在于永久代中
                              • 在执行一项特别大的 Hudson 作业时,我的 PermGen 快用完了……这为我解决了问题。
                              • @TimHowland,如果根本原因不是类加载器泄漏,只是您的 Web 应用程序中的类/静态数据过多,它可以是永久修复。
                              • 从源代码构建 jenkins/hudson 时遇到与 HDave 相同的问题。
                              【解决方案28】:

                              我有 Hibernate+Eclipse RCP 的组合,尝试使用 -XX:MaxPermSize=512m-XX:PermSize=512m,它似乎对我有用。

                              【讨论】:

                                【解决方案29】:

                                您最好尝试 -XX:MaxPermSize=128M 而不是 -XX:MaxPermGen=128M

                                我不知道这个内存池的确切用途,但它与加载到 JVM 中的类的数量有关。 (因此,为 tomcat 启用类卸载可以解决问题。)如果您的应用程序在运行时生成和编译类,则更有可能需要比默认值更大的内存池。

                                【讨论】:

                                【解决方案30】:

                                如果你在 Eclipse IDE 中得到这个,即使在设置了参数之后 --launcher.XXMaxPermSize-XX:MaxPermSize 等,如果您遇到同样的错误,很可能是 Eclipse 使用了错误版本的 JRE,该版本可能已由某些第三方应用程序安装并设置为默认值。这些有缺陷的版本不会获取 PermSize 参数,因此无论您设置什么,您仍然会不断收到这些内存错误。因此,在您的 eclipse.ini 中添加以下参数:

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

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

                                【讨论】:

                                  猜你喜欢
                                  • 2012-11-25
                                  • 2011-04-20
                                  • 1970-01-01
                                  • 2010-09-07
                                  相关资源
                                  最近更新 更多