2009-03-23 7 views
18

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

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

私は、私が期待していることを説明するための簡単な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が(期待されているもの)で行われているが、メモリが唯一の第三GCから始まるOSに返送された後、内部ヒープは無料です。 4番目以降は、割り当てられた全メモリがOSに返されます。

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

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

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

ありがとうございました。

+0

タグが完全にあなたのコードを食べました –

+0

Stackoverflowの構文強調機能を使用するために少しコードを再フォーマットしました。あなたが気にならないようにしてください。 –

+0

ありがとう、私は正しく表示されませんでした。 私は不満はありません。私はちょうどここに新しいです;-) –

答えて

15

tuning guideに記載されているように、Java 5以降のOSへのヒープリターンを制御するには、-XX:MaxHeapFreeRatioオプションを使用します。

ご質問がthis oneとは意味が異なると思われる場合は、どうかご指摘ください。

+0

あなたの返事をありがとう、私はそれらのヒントといくつかのテストを行います。 –

+0

彼の質問の一部は、リンクされた質問とは違って、 "あなたが戻ってくる仮想メモリを持っているならば、マシンのメモリを全面的に確保するのは安全です"と思われます。 – Kai

7

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

第二に、あなたは実際のjavaのあなたの呼び出しで

-verbosegc -XX:+PrintGCDetails 

を使用してGCで何が起こっているかを監視したいと思います。または、JConsoleを使用して、実行しているように聞こえます。しかし、System.gc()はあなたが間違ったものを数えているのを怖がっています...

私は、2番目または3番目のガベージコレクションがメモリを解放すると言うと、ガベージコレクションGCへのリクエストはGCではありません。したがって、ログ(interpret them this way)でPrintGCDetailsが印刷されていることを確認してください。

は、実際には私の問題は、私は、サーバー上で複数のCitrixクライアントセッションを実行する必要があるということですが、私はほんの数高い消費メモリを持っている(できるだけ早くメモリを解放するために、サーバー上で実行中のJVMを希望します私のアプリケーションの機能)。

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

私は完全にあなたがこのようにJavaのヒープをマイクロ管理したくないと信じています。

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

+0

これは、JVM自体ではなく、OSとJVM間のメモリ交換に関する質問には対処しません。 – erickson

+0

@erickson - そうです、内部のJVMヒープコメントを削除してください。彼は大きすぎるヒープを指定していて、そうする必要がないように思えました。しかし、そうではないようです。 – Kai

0

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

+2

あなたの提案は、少なくとも、各プロセスのJVMヒープの許容サイズを掛けたプロセスの数と同じくらい多くの仮想メモリを割り当てることです。たとえば、1GOの最大ヒープを持つ10プロセス、次に仮想メモリのプラスマイナス10GBが必要ですか? –

+0

ええええええええええええええええええええええええええええええええええええええええは完全に公演を殺すことができない – LtWorf

関連する問題