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

java。郎。OutOfMemoryError:永久代空间

这是一个典型的休眠/访问用户+借助该/JSF上运行的应用程序Tomcat6和JAVA1.6.显然,这可能会发生后重新部署一个申请几次。

是什么原因造成的以及可以做些什么以避免?我怎样解决这问题吗?

有帮助吗?

解决方案

解决办法是添加这些标志JVM命令行时Tomcat是开始:

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

你可以做到这一点的关闭tomcat服务,然后进入Tomcat/bin directory和运行tomcat6w.exe.在"Java"栏,添加参数"Java选项"。点击"OK",然后重新启动服务。

如果你得到一个错误 指定的服务并不存在,因为已安装的服务 你应该运行:

tomcat6w //ES//servicename

哪里 服务名称 是的服务器名称作为观察服务。msc

资料来源:orx的评论 Eric的敏捷的回答.

其他提示

你最好试试 -XX:MaxPermSize=128M 而不是 -XX:MaxPermGen=128M.

我不能告诉精确使用这个存池,但它必须做的类的数量载入JVM。(因此能使类的卸载于tomcat可以解决的问题。) 如果应用程序生成和编制课程在运行,它更有可能需要存储池大于默认。

应用程序服务器的永久代错误,这种情况发生后,多个部署是最有可能引起通过引用持有容器进入你的旧应用程序'类装入器.例如,使用定制日志的水平类将导致参考文献将举行的应用程序服务器的类装入器。你可以检测到这些跨类装入器的泄漏通过使用现代化(JDK6+)JVM分析工具,例如jmap和jhat来看待这类继续保持在你的程序,并重新设计或消除其使用。通常的嫌疑犯的数据库,记录器和其他基框架级的图书馆。

看看 类装入器泄漏:可怕的"java。郎。OutOfMemoryError:永久代空间"异常, ,特别是它的 随后.

常见的错误的人做是想堆空间和永久代空间是一样的,这是不真实的。你可以有很大的空间留在该堆中,但仍可运行的存在永久代.

常见的原因的内存在永久代是类装入器。每当一类被载入JVM,其所有的元数据,以及与类装入器,保存在永久代的区域和他们的将垃圾收集类装入器在其中载入他们准备收集垃圾。在情况类装入器已经存储器泄露于所有类载入通过它将保留在记忆和引起永久代内存一旦你重复了几次。经典的例子是 Java。郎。OutOfMemoryError:永久代空间在Tomcat.

现在有两种方式来解决这个:
1.找到原因的存储器的泄漏,或者如果有任何记忆丢失。
2.增加尺寸的永久代空间使用JVM param -XX:MaxPermSize-XX:PermSize.

你还可以检查 2解决方案。郎。OutOfMemoryError 在Java的更多详细信息。

使用命令行参数 -XX:MaxPermSize=128m 对于一个太阳JVM(显然代128为无论大小,你需要).

尝试 -XX:MaxPermSize=256m 如果它持续存在,尝试 -XX:MaxPermSize=512m

加入 -XX: MaxPermSize = 128m (你可以尝试,其最好的作品)到 VM参数 为我使用日食ide。在大多数JVM, 默认PermSize 是周围 64MB 它运行的存储器,如果有太多的类或数量巨大的字符串中的项目。

对于食,它也是在描述 答案.

步骤1 :双击tomcat服务器 服务器

enter image description here

步骤2 : 打开发射Conf 和add -XX: MaxPermSize = 128m 要结束现有的 VM arguements.

enter image description here

我一直撞我的头靠这个问题,同时部署和取消部署一个复杂的网络的应用的太多,我想添加一个解释我的解决方案。

当我应用程序部署在阿帕奇Tomcat,一个新的类装载器是为了这一应用程序。这类装入器随后被用来装载的所有应用程序的课程,并在取消部署,一切都是应该走得很好。然而,在现实中,这不是很简单的。

一个或更多的课程期间创建的网络应用程序的生活有一个静态的基准,在这过程中引用的类装入器。作为参照最初是静态的,任何数量的垃圾收集将清洁此参考了-类装入器,和所有类的装载的,是这里停留。

和之后的一对夫妇重新部署,我们遇到的OutOfMemoryError.

现在这已成为一个相当严重的问题。我可以确保Tomcat重新启动后的每一个重新部署,但这需要整个服务器上,而不是只是该应用程序正在重新部署,这往往是不可行的。

因此,不是我放在一起解决方案中的代码,其工作在Apache Tomcat6.0.我不是测试的任何其他应用程序服务器,并且必须强调, 这是非常可能的未来工作没有改变任何其他应用程序服务器.

我还想说,我个人讨厌这个代码, 没有人应该使用这个作为一个"速战速决"如果现有的代码可以被改变以使用适当的关闭和清理方法.唯一的时间,这应该使用是否有一个外部图书馆你的代码依赖于(在我的情况下,这是一个半径客户),没有提供一种手段来清理它自己的静态引用。

无论如何,在用的代码。这应该叫做在那里的应用程序是取消部署--例如servlet的销毁方法或(更好的做法)的一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();

或者,可以切换到JRockit其处理永久代不同,那么阳光的jvm。它一般具有更好的业绩。

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

1)增加了永久代记忆的大小

第一件事一能做的就是让大小的常驻代堆空间更大。无法做到这一点与通常的–Xms(设定初期堆大小)和–X(设定的最大堆大小)JVM的论点,因为如前所述,常驻代堆空间是完全独立于常规Java堆空间, 这些参数设置空间定期Java堆空间。然而,也有类似的论点,其中可使用(至少与太阳/们可根据最新的技术提供一些jvm),以使大小的常驻代堆更大:

 -XX:MaxPermSize=128m

默认是64m.

2)使扫

另一种方式照顾好是允许类被卸载所以你永远不会永久代运行:

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

那样的魔术工作为我的过去。有一件事不过,有一个显着的表现贸易在使用那些因为永久代扫会做出这样一个额外的2请求为每个请求你让或沿着这些线路的东西。你会需要平衡使用的折衷。

你可以找到详细的这个错误。

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

java.lang.OutOfMemoryError: PermGen 空间信息表明,常驻代的区域在存储器是用尽。

Java的任何应用程序是允许使用数量有限的记忆。的确切数量的内存特定应用可以使用指定期间申请的启动。

Java存储器被分成不同的区域可以看出,在以下图:

enter image description here

元空间:一个新的存储空间出生的

The JAVA8热点JVM是现在使用当地记忆为代表的级元数据和元空间被称为;类似于Oracle JRockit和IBM JVM。

好消息是,它意味着没有更多的 java.lang.OutOfMemoryError: PermGen 空间问题,并不需要你来调和监测这一存储空间使用了 Java_8_Download 或者更高。

我有问题我们在这里谈论我的情况是食-赫利俄斯+tomcat+jsf和你在做什么是制作一个部署一个简单的应用程序,以tomcat。我是显示出同样的问题,解决这个问题如下。

在日食去 服务器 卡双击的注册服务器在我的情况tomcat7.0,它打开了我的文件服务器的一般登记的信息。在部分 "一般信息" 点击链接 "打开发射配置" 这打开了执行服务器选择的参数标签VM参数增加的结束这两个项目

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

并准备。

最简单的答案,这些天是使用Java8.

它不再留存储器专门为永久代空间,允许永久代存储器的共同与定期存池。

请记住,你将需要删除所有非标准 -XXPermGen...=... JVM启动的参数,如果你不想Java8至抱怨说,他们没有做任何事情。

  1. 开tomcat7w从Tomcat的bin directory或类型监测Tomcat在开始菜单 (a签窗口打开了与各种服务的信息)。
  2. 在Java选择文本区域追加这一行:

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

彼尔姆艮空间错误的发生是由于使用大型空间,而不是jvm提供空间以执行的代码。最好的解决这个问题在UNIX操作系统被改变一些结构上的庆典的文件。下列步骤解决这个问题。

运行命令 gedit .bashrc 在终端。

创建 JAVA_OTPS 变量与以下价值:

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

节省的庆典的文件。运行命令exec击在终端。重新启动服务器。

我希望这一做法将在你的问题。如果使用Java version低于8这个问题发生的时候。但是如果您使用的Java8的问题从来没有发生。

增加常任代大小或调整的GC参数将不会帮助如果你有一个真正的记忆丢失。如果应用程序或某个第3方图书馆使用、泄漏舱装载机的唯一真正和永久解决办法是找到这个漏洞并进行修复。有些工具,可以帮助您,最近的一个是 Plumbr, 刚刚发布了新版本的需要的能力。

此外,如果您使用的是log4j在你的网络应用程序,检查这段log4j 文档.

看来,如果您使用 PropertyConfigurator.configureAndWatch("log4j.properties"), 你会引起记忆泄漏时,你来取消部署webapp.

我有一个组合的休眠+蚀要尝试使用 -XX:MaxPermSize=512m-XX:PermSize=512m 并且它似乎是为我工作。

设置 -XX:PermSize=64m -XX:MaxPermSize=128m.以后你也可以尝试增加 MaxPermSize.希望这会的工作。同样为我工作。仅设置 MaxPermSize 不是为我工作。

我尝试了几种答案的唯一的事情是什么最后做的工作就是这样配置的编译器插在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>

希望这一帮助。

解决这对我来说,作为;然而,我注意到,servlet重新启动的时候更糟糕,所以它虽然是更好的生产,它是一种拖在发展。

在配置存储器的性质取决于你的应用程序。

你在做什么?

什么样的交易金额进动?

多数据都是你装?

等等。

等等。

等等

也许你可以分析应用程序,并开始清理一些模块从你的应用程序。

显然,这可能会发生后重新部署的应用程序几次

Tomcat有热的部署,但它消耗的存储器。尝试重新启动您的容器一旦在一段时间。你也需要知道的内存数量需要运行中的生产模式,这似乎是一个很好的时间为这项研究。

他们说,最新的转Tomcat(6.0.28或6.0.29)处理任务的重新部署servlet 很多 更好。

我跑到完全相同的问题,但不幸的是,没有建议的解决方案真正为我工作。该问题没有发生在部署期间,我既没有做任何热的部署。

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

这个链接 (还提到此前)没有提供足够的内部解决的问题。移动jdbc(mysql)驱动的网-INF并入java运行环境/lib/ext/文件夹似乎已经解决了这个问题。这不是理想的解决方案,因为提升到一个新的java运行环境将需要重新安装的驱动程序。另一名候选人,可能会导致类似的问题是log4j,所以您可能想要移动那个为好

第一步,在这种情况下是检查是否GC允许卸载类永久代.标准JVM是相当保守在这方面类生活直到永远。所以一旦装、类住在存储器,甚至如果没有代码是使用它们了。这可以成为一个问题,当应用程序创造了大量的课程动态所产生的类是不必要长的时间。在这种情况下,允许JVM卸类定义可以是有帮助的。这可以通过增加一个构成参数,以启动脚本:

-XX:+CMSClassUnloadingEnabled

通过默认这是假的,因此,要使这个你需要明确地设置下列选项中Java的选择。如果你启用CMSClassUnloadingEnabled,GC将扫永久代太和消除这类不再使用。记住,这个选项将工作,只有当UseConcMarkSweepGC还启用了采用以下选项。所以当运行ParallelGC或者,上帝保佑,序GC,确保已设置你的GC CMS通过指定:

-XX:+UseConcMarkSweepGC

分配Tomcat更多的存储器是不适当的解决方案。

正确的解决办法是做一个清理后的上下文中被销毁和重建(热署).该方案是停止存储器的泄漏。

如果你Tomcat/网络应用程序服务器是在告诉你,未能注销的司机(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>  

"他们"是错误的,因为我运行6.0.29和有同样的问题,甚至是在设定之后所有的选项。如蒂姆*霍兰上面所说的,这些选项只有把不可避免的。他们允许我重新部署3次击中的错误,而不是的我每次重新部署。

在情况下你都该在日食IDE,甚至是在设定之后的参数 --launcher.XXMaxPermSize, -XX:MaxPermSize, 等等,如果你仍然是得到同样的错误,它最有可能是食是使用越野车的版本java运行环境,这将已经安装了通过一些第三方应用程序和设置为默认。这些车的版本不拿起PermSize参数和所以不管什么,你仍然保持获得这些记忆的错误。所以,在你的食。ini添加以下参数:

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

另外,还要确保你设定的缺省java运行环境中的偏好在日食的正确版本。

只有这样,为我工作是与JRockit JVM。我MyEclipse8.6.

JVM堆存储的所有对象产生的一个运行Java程序。Java使用 new 操作者创建的对象和记忆的新对象是分配上的堆在运行时间。垃圾收集机制的自动释放了存储器包含的对象不再被引用的程序。

我有类似的问题。我是JAVA7+家3.0.2+支柱2.0+谷歌题之一,因的依赖注射基础的项目。

每当我试图运行 mvn clean package 命令,这是显示以下错误和 "建立失败" 发生的

org.apache.专家.稳赚不赔的.工具.SurefireReflectionException:java。郎。反映。InvocationTargetException;嵌套的例外是java。郎。反映。InvocationTargetException:空 java。郎。反映。InvocationTargetException 所引起的:java。郎。OutOfMemoryError:永久代空间

我尝试了所有上述有用的技巧和技巧,但不幸的是,没有为我工作。什么工作对我来说是描述的步骤如下:=>

  1. 去你的pom.xml
  2. 搜索 <artifactId>maven-surefire-plugin</artifactId>
  3. 添加一个新的 <configuration> 元素,然后 <argLine> 子元件,其中传递 -Xmx512m -XX:MaxPermSize=256m 如下图所示=>

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

希望这有帮助,高兴方案)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top