java - 調査 - ネイティブ メモリーが使い尽くされました




JVMがメモリをOSに返送する (2)

私はあなたが測定可能な減速を見るまで心配しないでしょう。 プロセスが使用していないメモリが割り当てられている場合、OSは必要に応じて未使用のチャンクをディスクにスワップします。

JVMのメモリ管理に関する質問があります(少なくともSUNのものでは)。

JVMが未使用のメモリをOS(私の場合はWindows)に送り返すという事実を制御する方法を知りたい。

私は、私が期待していることを説明するための簡単なJavaプログラムを書いた。 -Dcom.sun.management.jmxremoteオプションを付けて実行すると、jconsoleなどでヒープを監視することもできます。

次のプログラムを使用します。

package fr.brouillard.jvm;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.List;

public class MemoryFree {
    private BufferedReader reader = new BufferedReader(new
        InputStreamReader(System.in));
    private List<byte[]> usedMemory = new LinkedList<byte[]>();
    private int totalMB = 0;
    private int gcTimes = 0;

    public void allocate(int howManyMB) {
        usedMemory.add(new byte[howManyMB * 1024 * 1024]);
        totalMB += howManyMB;
        System.out.println(howManyMB + "MB allocated, total allocated: " +
                totalMB + "MB");
    }

    public void free() {
        usedMemory.clear();
    }

    public void gc() {
        System.gc();
        System.out.println("GC " + (++gcTimes) + " times" );
    }

    public void waitAnswer(String msg) {
        System.out.println("Press [enter]" + ((msg==null)?"":msg));
        try {
            reader.readLine();
        } catch (IOException e) {
        }
    }

    public static void main(String[] args) {
        MemoryFree mf = new MemoryFree();
        mf.waitAnswer(" to allocate memory");
        mf.allocate(20);
        mf.allocate(10);
        mf.allocate(15);
        mf.waitAnswer(" to free memory");
        mf.free();
        mf.waitAnswer(" to GC");
        mf.gc();
        mf.waitAnswer(" to GC");
        mf.gc();
        mf.waitAnswer(" to GC");
        mf.gc();
        mf.waitAnswer(" to GC");
        mf.gc();
        mf.waitAnswer(" to exit the program");

        try {
            mf.reader.close();
        } catch (IOException e) {}
    }
}

最初のGCが完了すると(予想される)内部ヒープは解放されますが、メモリは3番目のGCからOSに返されます。 4番目以降は、割り当てられたメモリ全体がOSに返されます。

この動作を制御するためのJVMの設定方法は? 実際、私の問題は、サーバー上で複数のCITRIXクライアントセッションを実行する必要があることですが、サーバー上の実行中のJVMができるだけ早くメモリを解放したいと思っています。

この動作を制御できない場合は、OS仮想メモリを増やし、代わりにOSの仮想メモリを増やして、パフォーマンスの問題がなくてもOSを使用できるようにしてください。 例えば、十分な仮想メモリを持つ4GBサーバーには、1GBメモリの10個のJavaプロセス(ヒープ内に実際に割り当てられたオブジェクトが100MBのみ)があるという問題があります。

私は他の人たちがすでにそのような質問/問題に直面していたと思います。

ご協力いただきありがとうございます。


まず第一に、System.gc()は何もしません。 あなたは、あなたが示唆している方法でガベージコレクションを行うことに本当に頼ることはできません。

次に、GCを実際に使用しているかどうかを監視する必要があります。

-verbosegc -XX:+PrintGCDetails 

あなたのjavaの呼び出しで。 または、JConsoleを使用して、実行しているように聞こえます。 しかし、System.gc()はあなたが間違ったことを数えているのを恐れています...

私は、2番目または3番目のガベージコレクションがメモリを解放すると言うとき、ガベージコレクションを誤って取り込んでいるだけだと思う​​。 GCへのリクエストはGCではありません。 そのため、PrintGCDetailsが出力するログを確認してください( このように解釈する )。

実際、私の問題は、サーバー上で複数のCITRIXクライアントセッションを実行する必要があることですが、サーバー上の実行中のJVMができるだけ早くメモリを解放したいと思っています。

あなたの問題は有効ですが、あなたがしようとしている解決策は少し日よけです。 JVMは、このような理由から、ヒープサイズを必要とするため、この領域を実行することが保証されています。アプリケーションを起動し、JVMのヒープサイズを待ってから、別のマシン上のリソースをオーバーブッキングしていることを示します。 あなたが思っていたよりも多くのメモリをアプリケーションが取ってしまえば、それはすべて吹き飛ぶだろうが、それは権利があるからだ。

この方法でJavaのヒープをマイクロ管理したくないと私は十分信じています。

http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.htmlを十分に読んで世代を理解し、より大きい/より小さいヒープのトレードオフが何であるかを理解してください。





jvm