JVMでヒープサイズが固定されているのはなぜですか?


20

JVMを固定ヒープサイズで実行する必要がある理由(JVMをあまり多くチェックしなかったが、そのようにしないものは見たことがありません)を誰かが説明できますか?単純な連続したヒープに実装する方が簡単ですが、Sun JVMは10年以上前のものなので、これを改善する時間があったと思います。

起動時にプログラムの最大メモリサイズを定義する必要があるのは1960年代のことのように思え、OS仮想メモリ管理との悪い相互作用があります(GCはスワップアウトされたデータを取得し、Javaプロセスのメモリ量を判断できません)実際に OS側から使用して、無駄なVM空間の膨大な量は、(私が知っている、あなたは...あなたの空想の48ビットマシン上で気にしません))。また、JVM内に小さなオペレーティングシステム(EEアプリケーションサーバー、OSGi)を構築しようとするさまざまな悲しい試みは、この状況で少なくとも部分的に責任があると思います。システム上で複数のJavaプロセスを実行すると、ピーク時に使用する必要があるメモリをそれぞれに割り当てます。

驚くべきことに、Googleは私が期待するような怒りの嵐を降ろしませんでしたが、固定ヒープサイズを見つけて事実を受け入れるだけの何百万という人々に埋もれてしまったのかもしれません。


EEアプリケーションサーバーの設計は、JVM自体がある程度のスペースを必要とするため、この「状況」がなくても完全に理にかなっており、スレッド間の切り替えはプロセス間の切り替えよりも安価です。これが90年代後半にJavaを大きくした理由の1つです。
マイケルボルグワード

これは一種の暴言であり、あなたはそれにどれだけ考えたのだろうか。たとえば、ヒープ制限がない場合、GC /スワップの相互作用はどのように変わりますか?VMスペースはどのように浪費されますか?使用するかどうかにかかわらず、2 / 3Gbのスペースを取得します。そのスペースの限界を超えている場合は、固定ヒープまたはフローティングヒープのどちらでもかまいません。さらに言えば、複数のJVMはスワップ(マシンの目的に合わせて適切に設定する必要があります)以外を無駄にしますか?
kdgregory

2
それは一種の暴言ですが、Javaベースのプラットフォームを作成および操作する長年の日々の経験から知らされています。スワップを実行しない場合(暴走プロセスが割り当てるスペースを使い果たすまで20分間システムが応答しなくなるため)、安定性の理由でメモリオーバーコミットをオフにします(OOMキラーは被害者を選ぶのにあまり適していません) )、あなたはVMスペースを気にし、以下の人々が示唆していることに反して、-Xmx2048mでJava VMを起動すると、1つの変数を持つプログラムにすぐに2GBの仮想メモリが割り当てられます(少なくともLinux上のSun JVMでは)。
themel

素晴らしい質問です。同じことを不思議に思っています。しかし、ここでqに示されている「事実」と答えは正しいですか?
マーティンBa

あなたが探していた反応については、単にサンバグトラッカーに沿ってモージー...例えば、hereherehere。それらを読んでinする怒りを感じてください:)
基本的な

回答:


23

あなたは間違っている。JVMのヒープサイズは固定されておらず、制限されています。

  • -Xmxは最大ヒープメモリサイズを設定します
  • -Xmsは最小ヒープメモリサイズを設定します

上限の設定はいくつかの理由で必要です。まず、アクションを開始するタイミングをガベージコレクターに通知します。第二に、JVMが大量のメモリを消費してマシン全体を詰まらせるのを防ぎます。最小ヒープサイズは、おそらくプログラムが必要とするメモリの量を確保し、メモリが不足するのを防ぐのに役立ちます(他のプロセスが過度に消費するため)。


9
いいえ分は、多くの繰り返しヒープが増加する結果として割り当てる必要があるときに、ページングが物理RAMが不足して対処します低速の起動を避けるために、デフォルトで
ラチェットフリーク

@ratchetfreakそれは私の2番目の推測
でした

@ user281377これが当てはまる場合、最大ヒープメモリサイズなしでC#をどのようにうまく実行できますか?
cmorse

cmorse:推測しかできません。Javaは、多くのアプリケーションがリソースを共有し、厳密に適用される制限が望ましい大規模サーバーをターゲットにしているのに対し、.netはPCおよびより小さく専用のサーバー向けに作られています。
user281377

@ user281377:ヒープスペースを使い果たしたJavaアプリケーションは、一般に非常に不十分に処理され、通常はクラッシュするか、その後非常に不安定になります。また、ASP.netは大規模サーバーと小規模サーバーの両方で正常に実行されます。私が本当に得ていないのは、デフォルトでJavaがこの制限を強制する理由です。私は彼らの決定の背後にある理由から聞きたいです...彼らには正当な理由があると確信しています。
cmorse

6

答えはJavaの遺産と関係があると思います。もともとは組み込みシステムに使用される言語として設計されたものであり、明らかにリソースが制限されており、プロセスが単に利用可能なものを飲み込んで欲しくありません。また、リソース制限を設定できる場合、サーバー上のリソースのプロビジョニングが容易になるため、システム管理にも役立ちます。最新のJVMは複数の非連続ヒープを使用しているように見えますが、もちろんすべては、コードに対して単一のヒープとして表示されます。

(FWIW、Appleのダーウィン以前のMacOSバージョン(とにかくSystem 7までで、これは私が最後に使用したものでした)でプログラムのメモリ要件を指定する必要がありました。


1
+1-(1)実際に質問に対処した唯一の回答であり、(2)もっともらしいこと。
kdgregory

2

あなたは、GCを与えるために必要ないくつかのメカニズムを実行するためにそれを伝えるために、またはあなたのプログラムが全体の仮想メモリ空間を埋めるれます。GCをトリガーする多くの代替方法があります:経過時間、割り当ての数、割り当ての数、おそらく今は考えられない他の方法です。IMOはどれも、単にメモリ境界を設定し、割り当てられたスペースがその境界に達したときにGCを実行するほど良いものではありません。

重要なのは、正しい境界を設定することです。私-msは「これは私のアプリが必要とするメモリ-mx量」であり、「この量を超えてはならない」と考えています。実稼働展開では、2つは等しくない場合は近く、実際に測定された要件に基づいている必要があります。

「無駄な」仮想メモリについてのあなたの懸念は見当違いです。それは仮想であり、(ほとんど)無料です。はい。ヒープの割り当てを大きくしすぎると、スレッドを起動できなくなったり、メモリマップファイルをロードできなくなります。しかし、それはアプリケーション設計の一部です。リソースが不足しているため、アプリケーションを実行できるようにリソースを分割する必要があります。メモリのトップに達するまで拡張する「Cスタイル」ヒープでは、基本的な問題は同じであり、問​​題が発生するまで考える必要はありません。

すべての書き込み可能セグメントはスワップからのコミットメントを必要とするため、大きなヒープが「無駄」になる可能性があるのはスワップスペースだけです。ただし、これはシステム設計の一部です。同じボックスで多数のJVMを実行したい場合は、スワップを増やすか、ヒープ割り当てを減らします。彼らがスラッシングを始めたら、あなたはシステムを使いすぎようとしている。メモリを追加購入します(32ビットプロセッサをまだ実行している場合は、新しいボックスを購入します)。


1
ただし、GCを実行するためのしきい値は、プログラムによる合計メモリ使用量を超えることができない固定しきい値とは関係ありません。(実際、そうすべきではありません。ヒープが大きく、GCがいっぱいになったときにしかGCができない場合、必然的にGCの期間はまれですが長い期間になります)。世代別ガベージコレクションを参照してください。
ベン

@ベン-うん、あなたは正しい。そして、2番目の文は、選択肢があることを指摘しています。ただし、一般的なケースでは、固定サイズのヒープがGCを管理する間違った方法であることに同意しません。適切に調整されたJVMは、「正しい」ヒープサイズを使用します。私の経験では、JVMが適切に調整されていないと、長いGCの一時停止が発生します。そして、多くの場合、「正しい」ヒープサイズは、予想よりはるかに小さくなります。
kdgregory

-2

user281377にあるように、プロセス消費できるメモリの上限のみを指定します。もちろん、アプリケーション自体は必要なスペースのみを取得します。

デフォルトの上限があるべきかどうかは、賛否両論の別の問題です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.