无法创建PermGen错误

Art*_*äpp 4 java memory memory-management permgen

这是家庭作业,不会撒谎.我需要编写一个程序,它将生成"java.lang.OutOfMemoryError:PermGen space"错误.

由于我无法参加讲座,我昨天做了几个小时的研究,这是我到目前为止所做的.

起初我创建了一个程序,我不断得到这个错误:

java.lang.OutOfMemoryError: GC overhead limit exceeded
Run Code Online (Sandbox Code Playgroud)

好的,所以我做了一些更多的研究并理解我没有得到PermGen错误,因为虽然我创建了对象(String对象)但我没有再次使用它们,所以它们被认为是Garbage.所以我改变了我的代码,不断得到这个:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
Run Code Online (Sandbox Code Playgroud)

所以这是我在那时的代码:

import java.util.ArrayList;
import java.util.List;

public class Test {

public static void main(String[] args) {
    List<String> test = new ArrayList<String>();
    test.add(new String(""));

    for (;;) {
        for (int i = 0; i<test.size(); i++){
            test.add(test.get(i));
        }
    }
}
}
Run Code Online (Sandbox Code Playgroud)

同样在VM参数下我有"-XX:PermSize = 2m"(我尝试了不同的值).我被告知我的代码是错误的,因为它反复使用相同的字符串.所以我试图改变它,但我仍然没有成功.然后我发现了这段代码:( 导致java.lang.OutOfMemoryError: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());
}
Run Code Online (Sandbox Code Playgroud)

所以,如果我理解正确,这应该给我PermGen错误?但我仍然得到java堆错误.

另外我发现了这个:http: //javaeesupportpatterns.blogspot.com/2011/10/java-7-features-permgen-removal.html再次如果我理解正确,那么当使用java7时可能java堆空间错误就是我应该得到?那不可能再出现PermGen错误了吗?好的,所以我试图将编译器和项目版本更改为java 6.但仍然存在Java堆空间错误.

我知道我没有参加讲座是我的错,但是我可以帮助了解我在这里做错了什么或者我错过了什么?

Pet*_*iuk 6

首先,简单的一个班轮如何重现perm gen错误(只是递归调用main):

public class PermGenError {
    public static void main(String[] args) {
        main(new String[] { (args[0] + args[0]).intern() });
    }
}
Run Code Online (Sandbox Code Playgroud)

应该带参数启动:

whatever -XX:PermSize=8M -XX:MaxPermSize=8M
Run Code Online (Sandbox Code Playgroud)

第二,为什么你的例子不产生perm gen错误?您对字符串实习生的使用是正确的.但是在最新的JMV规范中,java虚拟机可以将内部化的字符串从永久生成移动到另一个.现实生活场景(发生在制作:-))是你可以看到perm gen 99%已满,应用程序极其缓慢且jvm没有抛出任何错误,因为它不断重组几代人之间的对象.

第三,我阅读并经常提到的任何GC /内存问题的最佳论文是使用5.0 Java [tm]虚拟机调优垃圾收集

编辑:

更新问题是:

示例工作正常,但是当我指定大的perm大小时仍然不起作用 - 获取'Java堆空间'

更新回答是:

指定更大的perm gen size时,需要注意两个地方:

  1. 所有物品首先进入年轻一代.因此,如果您的perm gen size大于第一代Java堆空间的大小将首先抛出.在这个特定的例子中,我使用了一个超过perm gen size的大字符串,以便重现错误.如果要重现'PermGen space',则还需要指定堆大小.例如:

    • -Xms2048m -Xmx2048m -XX:PermSize = 512M -XX:MaxPermSize = 512M - 将导致'PermGen space'(大堆,小perm gen)
    • -Xms512m -Xmx512m -XX:PermSize = 2048M -XX:MaxPermSize = 2048M - 将导致'Java堆空间'(小堆,大烫发)
  2. 第二个方面是堆被分成几代,堆本身的内存被分段.因此,当您指定512M的堆大小时,您无法将半千兆字节长的字符串放入内存中(因为字符串内部实现为数组,需要作为一个连续的块存储在内存中).你可以适应的最大值大约是这个大小的一半(这取决于内存碎片的严重程度).