3

多くの文字列操作を行うアプリケーションがあり、メモリに何も格納していないにもかかわらず、jvm メモリの使用量が非常に多いことに気付きました。

問題を示すためにサンプルアプリケーションを作成しました:ボタンが1つある単純なJFrameがあります

private void buttonDoWorkActionPerformed(java.awt.event.ActionEvent evt) {
    String randomString = "abc test garbagecollector";

    ArrayList<String> results;

    for(int i=0; i<100000; i++)
        results = doNothing(randomString.split(" "));

    results = null;//No effect
    System.gc();//No effect
}

private static ArrayList<String> doNothing(String[] words) {
    ArrayList<String> results = new ArrayList<String>();

    for (String word : words)
        results.add(word);

    return results;
}

このサンプルを実行すると、JVM はメモリ内で約 50Mo を使用し、ボタンを押すと 150Mo に上昇し、決してダウンすることはありません。編集:Windowsタスクマネージャーの「java.exe」プロセスを参照しています。

明らかに、私は多くの一時的な文字列のコピーを行っていますが、参照が失われると、それらがカーベージ コレクターによって解放されることを期待しています。

編集:関係ないかもしれませんが、Java 1.6 で 32 ビット バージョンと 64 ビット バージョンの両方を試しました。

4

2 に答える 2

4

itここには多くのレベルが表示される可能性があるため、意味を明確にする必要があります。GC で減少するものもあれば、減少しないものもあります。

GC 後のメモリ使用量を調べている場合、増加していないことがわかります。他の何かの増加が見られる場合は、最大メモリまたはその他の数値である可能性があります。

public static long memoryUsed() {
    return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}

public static void main(String... args) {
    String randomString = "abc test garbagecollector";

    System.gc();
    System.out.printf("Memory used before test started %.1f MB%n", memoryUsed() / 1e6);
    for (int t = 0; t < 5; t++) {
        List<String> results = new ArrayList<String>();

        for (int i = 0; i < 100000; i++) {
            for (String word : randomString.split(" "))
                results.add(word);
        }
        long beforeGC = memoryUsed();
        results = null;
        System.gc();
        System.out.printf("%d: before GC %.1f MB used, after GC %.1f MB used%n",
                t, beforeGC / 1e6, memoryUsed() / 1e6);
    }
}

版画

Memory used before test started 5.7 MB
0: before GC 61.8 MB used, after GC 5.8 MB used
1: before GC 44.3 MB used, after GC 5.8 MB used
2: before GC 44.3 MB used, after GC 5.8 MB used
3: before GC 44.3 MB used, after GC 5.8 MB used
4: before GC 44.3 MB used, after GC 5.8 MB used
于 2012-12-10T16:55:09.490 に答える
0

文字列はおそらくインターンされています。これは、VM 設計の決定に関連する Java と文字列の問題です。おそらく、VisualVM やその他のフレームワークを入手して、実行中の JVM に接続してオブジェクトを確認したり、ヒープ ダンプを実行して結果を確認したりできます。

于 2012-12-10T16:54:19.523 に答える