导致 java.lang.OutOfMemoryError: PermGen space 错误的算法

发布于 2024-09-26 00:17:44 字数 433 浏览 5 评论 0原文

我在 Sun JVM (1.6.0_21-b06) 上遇到 PermGen 空间错误(好吧,这是 Oracle :))。增加选项 -XX:MaxPermGen 值没有帮助。我知道 PermGen 是一个用于永久对象(例如类元数据)的空间。项目中的类数量不是很大~ 10 000。在崩溃之前,jvisualvm 显示 57MB 作为已使用的 PermGen。

我猜想某些算法占用了所有可访问的内存。有人知道导致 PermGen 溢出的算法示例吗?

UPD。我问这样抽象的问题,因为此刻我无法使用任何探查器 - 代码崩溃如此严重,以至于 jvisualvm 和 eclipse 停止响应。我需要使用kill -KILL {process_numer}从终端杀死java进程。我使用的是组织不良(但商业)的代码,其中包含许多线程和 JMS 消息传递。调试一团糟——我首先需要知道去哪里寻找。

I am getting PermGen space error on Sun JVM (1.6.0_21-b06) (Ok, it's Oracle :)). Increasing of option -XX:MaxPermGen value does not help. I know that PermGen is a space intended for permanent objects like class metadata. Count of classes in project is not so big ~ 10 000. Before crash jvisualvm shows 57MB as Used PermGen.

I guess that some algorithm occupies all accessible memory. Does someone know examples of algorithms that lead to PermGen overflow ?

UPD. I ask such abstract question, because in the moment I can not use any profiler - code crashes so hard that jvisualvm and eclipse stop to respond. I need than kill java processes from terminal with kill -KILL {process_numer}. I work with bad organized (but commercial) code that has many threads and JMS messaging. Debugging is a mess - I need some idea first where to look.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

风情万种。 2024-10-03 00:17:44

与其说是算法,不如说是实现。这是一种非常愚蠢的方法来生成填充 PermGen 空间的随机字符串:

    Random rnd = new Random();
    List<String> interned = new ArrayList<String>();
    for (;;) {
        int length = rnd.nextInt(100);
        StringBuilder builder = new StringBuilder();
        String chars = "abcdefghijklmnopqrstuvwxyz";
        for ( int i = 0; i < length; i++ ) {
            builder.append(chars.charAt(rnd.nextInt(chars.length())));
        }
        interned.add(builder.toString().intern());
    }

简而言之:实习字符串是一种会耗尽 PermGen 内存的东西。

It's not so much the algorithm as the implementation. Here's a really dumb way to generate random Strings that fills up PermGen space:

    Random rnd = new Random();
    List<String> interned = new ArrayList<String>();
    for (;;) {
        int length = rnd.nextInt(100);
        StringBuilder builder = new StringBuilder();
        String chars = "abcdefghijklmnopqrstuvwxyz";
        for ( int i = 0; i < length; i++ ) {
            builder.append(chars.charAt(rnd.nextInt(chars.length())));
        }
        interned.add(builder.toString().intern());
    }

In short: interning Strings is one thing that can eat up PermGen memory.

财迷小姐 2024-10-03 00:17:44

有两件事可能会导致 PermGen 空间问题:

  1. String.intern(String) 方法在 PermGen 堆中创建字符串。如果您进行了大量的驻留操作并直接(或间接)保留对驻留字符串的引用,则可以填充 PermGen。

  2. 类加载器在 PermGen 堆中创建 JVM 内部类描述符和代码段。如果您的应用程序执行大量动态类加载,并且类对象没有被垃圾回收,则可以填充 PermGen。

Java Web 应用程序的热重新部署依赖于动态加载,是 PermGen 问题的常见来源。根本原因通常是内存泄漏,涉及从某个对象到旧类加载器的隐藏引用。 (Tomcat 经常因此而“陷入困境”,但真正的问题通常是在正在重新部署的 Web 应用程序中。)

据我所知,@Michael Borgwardt 提到的 Proxy 案例也是 Proxy 实现生成类文件并将其加载到的结果苍蝇。

There are two things that are likely to lead to PermGen space issues:

  1. The String.intern(String) method creates Strings in the PermGen heap. If you do a lot of interning and directly (or indirectly) retain references to the interned Strings, you can fill PermGen.

  2. The classloaders creates JVM internal class descriptors and code segments in the PermGen heap. If your application does a lot of dynamic class loading, and the class objects don't get garbage collected, you can fill PermGen.

Hot redeployment of Java webapps relies on dynamic loading and is a common source PermGen problems. The root cause is typically a memory leak that involves a hidden reference from some object to an old classloader. (Tomcat often gets "stick" for this, but the real problem is typically in the webapp that is being redeployed.)

AFAIK, the Proxy case mentioned by @Michael Borgwardt is also a result of the Proxy implementation generating class files and loading them on the fly.

<逆流佳人身旁 2024-10-03 00:17:44

有人知道导致 PermGen 溢出的算法示例吗?

是的,但这有什么意义呢?如果您想修复此问题,请安装内存分析器工具(例如 jprobe 或 lambda 探针)并检查内存泄漏发生的位置,然后修复该问题。
现在举个例子:有数千种方法可以超过永久代空间。当我们继承一个使用 JMS 的应用程序时,我注意到一个项目。 jms 连接保持打开状态,应用程序在收到大量请求后几分钟内崩溃,并出现与您遇到的类似错误。需要注意的是:当我们从 jboss 迁移到 weblogic(迁移到 beajrockit)时,令人惊讶的是它自行修复了,或者至少承受了技术债务的打击。我的建议是无论如何,应该首先修复具有内存泄漏的错误代码,然后修补应用程序服务器和堆空间分配参数。

这是一个有用的链接,其中包含有关您收到的异常的一些信息。
http://www.jroller.com/agileanswers/entry/preventing_java_s_java_lang

编辑

这个链接可能有帮助
http://www.precisejava.com/javaperf/j2ee/JMS.htm

Does someone know examples of algorithms that lead to PermGen overflow ?

Yes but what is the point of this? if you want to fix this install a memory profiler tool like jprobe or lambda probe and check where the memory leak is happening, and fix that.
Now for the example: There are thousands of ways to exceed perm gen space. I had noticed on a project when we inherited an application where they were using JMS. The jms connections were left open, the application crashed within a few minutes after it got a lot of requests with a similar error like you are getting. Point to note: when we moved to weblogic from jboss (moved to beajrockit) amazingly it fixed itself or atleast took the blow of technical debt. My advice would be irrespective of this, bad code with memory leaks should be fixed first, then tinker with app servers and heap space allocation paramters.

Here is a useful link with some information on the exception you are getting.
http://www.jroller.com/agileanswers/entry/preventing_java_s_java_lang

EDIT

This link may be helpfull
http://www.precisejava.com/javaperf/j2ee/JMS.htm

霞映澄塘 2024-10-03 00:17:44

If you use java.lang.reflect.Proxy very intensively, that could eat up your PermGen space as well.

无语# 2024-10-03 00:17:44

查看内存分析器 - http://www.eclipse.org/mat/。它是一个java转储内存分析器。在发生意外错误后,它非常有用。

Check out memory analyzer - http://www.eclipse.org/mat/. It is a java dump memory analyzer. It is pretty useful after an unexpected error.

狼亦尘 2024-10-03 00:17:44

您是否使用不同的垃圾收集器?

如果花费太多时间进行垃圾收集,吞吐量收集器将抛出内存不足异常。例如,如果 JVM 花费超过 98% 的总时间进行垃圾回收,并且只回收不到 2% 的堆,则会抛出内存不足的预期。此功能的实现在 1.5 中发生了变化。政策是相同的,但由于新的实施,行为可能会略有不同。” “在 J2SE 平台版本 1.5 中,将选择吞吐量收集器作为服务器类计算机上的垃圾收集器。” http://java.sun.com/docs/hotspot/gc5.0 /gc_tuning_5.html

检查 页面。

Are you using a different garbage collector?

The throughput collector will throw an out-of-memory exception if too much time is being spent doing garbage collection. For example, if the JVM is spending more than 98% of the total time doing garbage collection and is recovering less than 2% of the heap, it will throw an out-of-memory expection. The implementation of this feature has changed in 1.5. The policy is the same but there may be slight differences in behavior due to the new implementation.” ” In the J2SE Platform version 1.5 the throughput collector will be chosen as the garbage collector on server class machines.” http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html

Check some instructions on this page.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文