4

これは宿題であり、嘘をつくつもりはありません。「java.lang.OutOfMemoryError:PermGenspace」エラーを生成するプログラムを作成する必要があります。

講義に参加できなかったので、昨日は何時間も研究をしましたが、これが今のところです。

最初にプログラムを作成しましたが、常に次のエラーが発生しました。

java.lang.OutOfMemoryError: GC overhead limit exceeded

さて、私はさらに調査を行い、PermGenエラーが発生しないことを理解しました。これは、オブジェクト(文字列オブジェクト)を作成したものの、それらを再度使用しなかったため、ガベージと見なされたためです。だから私は自分のコードを変更し、常にこれを手に入れました:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

だからこれは私がその時点で持っていたコードです:

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));
        }
    }
}
}

また、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());
}

それで、私が正しく理解していれば、これは私にPermGenエラーを与えるはずですか?しかし、それでもJavaヒープエラーが発生します。

また、私はこれを見つけました:http: //javaeesupportpatterns.blogspot.com/2011/10/java-7-features-permgen-removal.html 繰り返しますが、正しく理解していれば、java7を使用すると、おそらくjavaヒープスペースエラーが発生します。取得する必要がありますか?PermGenエラーを取得することはもう不可能ですか?さて、コンパイラとプロジェクトのバージョンをJava 6に変更しようとしましたが、それでもJavaヒープスペースエラーが発生しました。

講義に出席しなかったのは私のせいですが、ここで何が間違っているのか、何が欠けているのかを理解するために助けを借りることができます。

4

3 に答える 3

6

まず、perm genエラーを再現する方法を簡単に説明します(再帰的にmainを呼び出すだけです)。

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

パラメータを使用して起動する必要があります:

whatever -XX:PermSize=8M -XX:MaxPermSize=8M

第二に、なぜあなたの例はパーマ生成エラーを生成しないのですか?文字列インターンの使い方は正しいです。ただし、最新のJMV仕様では、Java仮想マシンは内部化された文字列を永続的な世代から別の世代に移動できます。実際のシナリオ(本番環境で発生:-))は、perm genが99%いっぱいで、アプリケーションが非常に遅く、jvmが世代間でオブジェクトを絶えず再シャッフルするため、エラーをスローしないことを確認できます。

第三に、GC /メモリの問題について私が読んで常に参照している最高の論文は、5.0Java[tm]仮想マシンを使用したガベージコレクションの調整です。

編集

質問の更新は次のとおりです。

例は正常に機能しますが、大きなpermサイズを指定している場合は機能しません-「Javaヒープスペース」を取得します

答えの更新は次のとおりです。

より大きなpermgenサイズを指定する場合は、次の2つの注意が必要です。

  1. すべてのオブジェクトは、最初に若い世代の1つに移動します。したがって、perm genのサイズが第1世代のJavaヒープスペースのサイズよりも大きい場合は、最初にスローされます。この特定の例では、エラーを再現するために、permgenサイズを超える1つの大きな文字列を使用しています。「PermGenスペース」を再現する場合は、ヒープサイズも指定する必要があります。例えば:

    • -Xms2048m -Xmx2048m -XX:PermSize = 512M -XX:MaxPermSize = 512M-「PermGenスペース」(大きなヒープ、小さなperm gen)になります
    • -Xms512m -Xmx512m -XX:PermSize = 2048M -XX:MaxPermSize = 2048M-「Javaヒープスペース」(小さなヒープ、大きなperm gen)になります
  2. 2番目の側面は、ヒープが世代に分割され、ヒープ自体のメモリが断片化されることです。したがって、512Mのヒープサイズを指定すると、0.5ギガバイトの長さの文字列をメモリに収めることができません(文字列は配列として内部的に実装され、1つの連続したチャンクとしてメモリに格納する必要があるため)。あなたが収まることができる最大のものはおそらくそのサイズの約半分です(それはメモリがどれほどひどく断片化されているかに依存します)。

于 2012-10-14T12:20:53.313 に答える
3

これPermGen Spaceは、Javaがクラス定義と内部データ(アプリケーションが作成および使用するデータではない)を格納するメモリ領域です。したがって、基本的に、大きくて賢いアプリケーションは必要ありません。このブログページでは、Javaメモリの構造と、さまざまな領域の責任について簡単に説明しています。

理論的には、(すでに行ったように)低パーマ生成スペースを定義することで、例外をすぐに取得できます-XX:PermSize=2m。次に、いくつかのライブラリをアプリケーションのクラスパスに追加します(Apacheコモンズ、おそらくHTMLUnitなど)。いくつかのjarをダウンロードすると、アプリケーションが起動し、クラスローダーがjarのクラス定義をPermGenスペースに格納しようとするとすぐにこのエラーが発生します。

これが機能しない場合は、Tomcatを使用してみてください。いくつかのライブラリをデプロイし、Webアプリマネージャーを介してアプリケーションを何度もリロードしてください。

この問題の原因となるアルゴリズムが必要な場合は、JVMパラメーターを使用して実行中のアプリケーションをデバッグできます-XX:+PrintGCDetails。これにより、GCが使用されるたびに使用されるPermGenスペースのサイズが表示されます。これは、正しい方向に進んでいるかどうか、およびどのメモリ領域を埋めているかを確認するのに役立ちます。PermGenスペースには、メソッドへの参照を持つ配列も格納されるため、これによって問題も解決できる可能性があります。

于 2012-10-14T12:01:44.727 に答える
1

それで、私が正しく理解していれば、これは私にPermGenエラーを与えるはずですか?しかし、それでもJavaヒープエラーが発生します。

java.lang.OutOfMemoryError:GCオーバーヘッド制限を超えました

うん。何が起こっているのかというと、メモリ不足になる可能性のあるプログラムがプロセスに多くの時間を費やすことを防ぐように設計されたJVMメカニズムにぶつかっているということです。

GCオーバーヘッド制限を超えましたを参照してください

これは、-XX:-UseGCOverheadLimitスイッチを使用して無効にできます。そうすれば、permgenのメモリが不足しているというOOMEが表示されることを期待しています。


これを取得している場合:

スレッド「メイン」の例外java.lang.OutOfMemoryError:Javaヒープスペース

問題は、permgenスペースが不足する前に、通常のヒープのスペースが不足していることです。

  • 通常のヒープサイズを増やします。
  • アプリケーションがこれらのインターンされたすべての文字列への参照を保持していることを確認してください。(到達不能になった場合、ガベージコレクションが行われ、permgenスペースが不足することはありません。)
于 2012-10-14T12:07:57.390 に答える