[解決済み] Javaで使用可能なメモリを取得する
質問
実行時にJVMに利用可能な残りのメモリを取得する良い方法はありますか?この使用例は、OutOfMemory エラーで突然死ぬのではなく、素敵なエラーメッセージ "あまりにも多くの人がこれを使用しているので、後でもう一度試してください" で新しい接続を拒否することによって、メモリ制限に近づいているときに優雅に失敗する Web サービスを持つことです。
これは、事前に各オブジェクトのコストを計算/推定することとは何の関係もないことに注意してください。原理的には、オブジェクトがどのくらいのメモリを消費するかを推定し、その推定値に基づいて新しい接続を拒否することができますが、これはちょっとハチャメチャで壊れやすいように思われます。
どのように解決するのですか?
William Brendelによるこのサンプルは、何らかの役に立つかもしれません。
EDIT: 私はもともとこのサンプルを提供しました (別のトピックでの William Brendel の回答へのリンク)。そのトピックの作成者 (Steve M) は、マルチ プラットフォームの Java アプリケーションを作成したいと考えていました。具体的には、ユーザーは実行中のマシンのリソース (ディスク領域、CPU、およびメモリ使用量) を評価する手段を見つけようとしていました。
これは、そのトピックで行われた回答のインライン トランスクリプトです。しかし、私の回答が受け入れられたにもかかわらず、それが理想的な解決策ではないことが、このトピックで指摘されています。
public class Main {
public static void main(String[] args) {
/* Total number of processors or cores available to the JVM */
System.out.println("Available processors (cores): " +
Runtime.getRuntime().availableProcessors());
/* Total amount of free memory available to the JVM */
System.out.println("Free memory (bytes): " +
Runtime.getRuntime().freeMemory());
/* This will return Long.MAX_VALUE if there is no preset limit */
long maxMemory = Runtime.getRuntime().maxMemory();
/* Maximum amount of memory the JVM will attempt to use */
System.out.println("Maximum memory (bytes): " +
(maxMemory == Long.MAX_VALUE ? "no limit" : maxMemory));
/* Total memory currently in use by the JVM */
System.out.println("Total memory (bytes): " +
Runtime.getRuntime().totalMemory());
/* Get a list of all filesystem roots on this system */
File[] roots = File.listRoots();
/* For each filesystem root, print some info */
for (File root : roots) {
System.out.println("File system root: " + root.getAbsolutePath());
System.out.println("Total space (bytes): " + root.getTotalSpace());
System.out.println("Free space (bytes): " + root.getFreeSpace());
System.out.println("Usable space (bytes): " + root.getUsableSpace());
}
}
}
ユーザーであるChristian Fries氏は、以下のように仮定するのは間違いであると指摘しています。
Runtime.getRuntime().freeMemory()
がメモリ不足のエラーが発生するまでに割り当てられるメモリの量を示していると考えるのは間違いです。
から
ドキュメント
のシグネチャーの返り値は
Runtime.getRuntime().freeMemory()
はこのようなものです。
を返します。 将来割り当てられるオブジェクトのために現在利用可能なメモリの総量の概算をバイト数で表したもの。
しかし、ユーザー Christian Fries は、この関数が誤って解釈される可能性があると主張しています。彼は、メモリ不足のエラーが発生するまでに割り当てられる可能性のあるメモリのおおよその量 (空きメモリ) は、次のように与えられる可能性が高いと主張しています。
long presumableFreeMemory = Runtime.getRuntime().maxMemory() - allocatedMemory;
とは
allocatedMemory
によって与えられる。
long allocatedMemory =
(Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory());
ここで重要なのは、空きメモリの概念との不一致です。ひとつは、オペレーティングシステムがJava仮想マシンに提供するメモリです。もうひとつは、Java Virtual Machine 自身が実際に使用しているメモリブロックのチャンクを構成するバイトの総量です。
Java アプリケーションに与えられたメモリが Java Virtual Machine によってブロック単位で管理されていることを考えると、このブロックの量は 空きメモリ の量は、Java アプリケーションが利用できるメモリと正確に一致しない場合があります。
具体的には、Christian Friesは、その使用方法を示すために
-mx
または
-Xmx
フラグを使用して、Java 仮想マシンが利用可能な最大メモリ量を設定します。彼は次のような機能の違いに注目しています。
/* Returns the maximum amount of memory available to
the Java Virtual Machine set by the '-mx' or '-Xmx' flags. */
Runtime.getRuntime().maxMemory();
/* Returns the total memory allocated from the system
(which can at most reach the maximum memory value
returned by the previous function). */
Runtime.getRuntime().totalMemory();
/* Returns the free memory *within* the total memory
returned by the previous function. */
Runtime.getRuntime().freeMemory();
クリスチャンは、次のように述べて回答を締めくくります。
Runtime.getRuntime().freeMemory()
は実際には推定可能な空きメモリと呼ばれるものを返します。将来のメモリ割り当てがその関数によって返される値を超えていなくても、Java 仮想マシンがホストシステムによって割り当てられた実際のメモリの塊をまだ受け取っていない場合、その関数によって返される値は
java.lang.OutOfMemoryError
がまだ生成される可能性があります。
結局のところ、使用する適切な方法は、アプリケーションの仕様に依存する程度が異なります。
役に立つかもしれない別のリンクを提供します。これは、ユーザー Richard Dormand が作成し、stones333 が回答した質問です。 使用されるデフォルトのJavaヒープサイズを決定することについての質問です。
関連
-
メモ帳でJavaプログラムをコンパイルして実行すると、Could not find or load main class ...というエラーが表示される。解決方法
-
CAS 5.1.8でhttpをサポートし、認証されていない認可サービスエラーのプロンプトが表示される問題を解決した。
-
[解決済み] JavaでInputStreamを読み込んでStringに変換するにはどうすればよいですか?
-
[解決済み] JavaでNullPointerExceptionを回避する方法
-
[解決済み] JavaにおけるHashMapとHashtableの違いは何ですか?
-
[解決済み] Java Mapの各エントリを効率的に反復処理するには?
-
[解決済み] Javaでメモリーリークを発生させるにはどうしたらいいですか?
-
[解決済み] JavaでArrayListではなくLinkedListを使用するのはいつですか?
-
[解決済み] Javaで文字列値からenum値を取得する方法
-
[解決済み】Javaではfinallyブロックは必ず実行されるのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン