2

私は、サーバー (tomcat) で同じ war ファイルの展開と展開解除のアクションを繰り返すと、PermGen OutOfMemoryError が発生する場所にいます。私の目標は、戦争がアンデプロイされたときにすべてのクラスを確実にアンロードすることです。

ここに私が持っているクラスがあります:

public class ClassA {
//static variables & methods
//instance variables & methods

    private EnumInsideClassA myState = EnumInsideClassA.VALUE1;

    private enum EnumInsideClassA
    {
        VALUE1,
        VALUE2
    }
}

ClassA の参照をすべてクリアしたところ、ClassA が表示されず、war がアンデプロイされたときにアンロードされました。ただし、列挙参照は引き続き表示され、ClassA$EnumInsideClassA はアンロードされません。

「myState」インスタンス変数のゲッターはなく、ClassA で使用されるだけです

どんな助けでも大歓迎です

4

2 に答える 2

1

問題は、enum インスタンスがクラスローダーによってアンロードされていないことです。テスト サーブレット プロジェクトがあり、それには列挙型しかありません。プライベートまたは内部クラスの列挙型である必要はありませんが、インスタンスが作成されるように少なくとも 1 回参照する必要があります。jvm が enum を特別なものとして扱っていないのは事実のようです。静的インスタンスでも同じ問題が発生します (つまり、カスタム クラスの静的インスタンスは、クラスローダーのアンロード時にガベージ コレクションを取得しません)。

さまざまな -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled を試しましたが、成功しませんでした。これは JVM 固有のものである可能性があります (私は Mac OS X を使用しており、これらのオプションはないようですが、-Xincgc も機能しませんでした: http://developer.apple.com/library/mac/#documentation /Java/Reference/Java_VMOptionsRef/Articles/JavaVirtualMachineOptions.html )。「java.lang.OutOfMemoryError: PermGen space」エラーの処理など、stackoverflow に関する多くの情報があります。

おそらく、この特定の問題 (サーブレットの再デプロイ) に対する最善の修正は、すべての列挙型をアンロードする必要のない jar に入れることです。

FIY: 私の環境は Mac OS X 10.6.8、Java 1.6.0_31 です。

于 2012-06-12T19:48:58.440 に答える
1

ただし、列挙参照は引き続き表示され、ClassA$EnumInsideClassA はアンロードされません。

参照が表示されている場合enumは、それらがどこにあるかを確認できるはずです。これで、enum クラスの非表示の static フィールドを介してアクセスできる enum 参照がいくつかありますが、これらは循環参照である必要があり、enum到達可能なままにするべきではありません。enumどこかに参照があるかどうかを確認してください。

于 2012-04-08T09:29:50.060 に答える