web-dev-qa-db-ja.com

Javaで定義されていないブールサイズ:なぜですか?

ブール値のサイズが定義されていないようです。以下は、私が見る2つのステートメントです Javaプリミティブデータサイズ

正確に定義されていない

さらに説明すると

ブール値は1ビットの情報を表しますが、その「サイズ」は正確に定義されたものではありません。

疑問が浮かんだのは、なぜJavaのブール値が1ビット(またはバイトが最小表現の場合は1バイト)で表現できないのか)でした。

しかし、私はそれがすでに https://stackoverflow.com/questions/1907318/why-is-javas-boolean-primitive-size-not-defined で回答されていることを確認します

jVMは、ローカル変数、メソッド引数、および式の値を保持するために使用される32ビットのスタックセルを使用します。 1セルより小さいプリミティブはパディングされ、32ビットより大きい(プリミティブおよびダブル)プリミティブは2セルを使用します。

バイト/文字/短いプリミティバのデータ型でもサイズが8/16/16ビットとして定義されていますが、32ビットも必要ですか?

また、ブールサイズは32ビットCPUでは32ビット、64ビットCPUでは64ビットと言えるでしょうか?

9
user3222249

TL; DR確かなことは、booleanが少なくとも1ビットを占有していることだけです。それ以外はすべてJVMの実装に依存します。

Java言語仕様はサイズを定義せず、値の範囲のみを定義します( 言語仕様 を参照)。したがって、booleanサイズだけではありませんこのレベルでは定義されていません。また、booleanには、falsetrueの2つの値があります。

仮想マシン仕様 は、boolean変数が値0および1のintのように扱われることを示しています。booleanの配列のみが特定のサポートを持っています。したがって、仮想マシンレベルでは、boolean変数はintと同じ量のスペースを占めます。つまり、1つのスタックセルを意味します。少なくとも4バイト、通常32ビットでは4バイトJavaおよび64ビットで8バイト。

最後に、JVMバイトコードを最適化されたCPU固有のマシンコードにコンパイルするHotSpotエンジンがあり、多くの場合、int- masked booleanの制限された値の範囲を推定できると思いますコンテキストと小さいサイズを使用します。

10
Ralf Kleberhoff

離れていくためにいくつかの概念があります:

  • Javaプログラミング言語自体、テキストプログラミング言語であり、
  • Java Virtual Machine byte-code&class file format、これは、元のJava言語ソースコードのバイナリコンパイルされたエンコーディングです。 Javaオブジェクトコードを保存、ロード、共有するための交換ファイル形式として使用されます。
  • 特定のJava Virtual Machine implementation、これはインタープリターになる可能性がありますが、多くの場合JITベースの実装ですが、
  • JITは、ハードウェアプロセッサで直接実行されるマシンコードを生成しました。

Java、プログラミング言語は、(C/C++とは異なり)sizeof演算子がないため、プリミティブ型の概念サイズを定義していません。言語構造を介してサイズを監視できないため、言語はそれらを定義する必要はありません。

@Ralfが指摘するように、Java言語はプリミティブ型の範囲を定義します。これらの範囲は、言語内の構成を介して観察できるため、プログラマーにとって非常に重要です。

言語はオブジェクトのサイズを照会できる計測機能を定義していますが、(1)これには計測が必要であり、(2)見積もりの​​みを提供し、(3)この照会はプリミティブ型には適用されませんまたはローカル変数。

jVMは、ローカル変数、メソッド引数、および式の値を保持するために使用される32ビットのスタックセルを使用します。 1セルより小さいプリミティブはパディングされ、32ビットより大きいプリミティブ(ロングおよびダブル)は2セルを使用します。

パディング引用は、交換メカニズムとして使用されているJVMクラスファイル形式の詳細を示しています(Java言語およびJVM実装とは異なります)。抽象マシンとJVMバイトコード。JITされたマシンコードを保持する必要はありません。

パディング引用は、通常スタック割り当てされているローカル変数/パラメーター/式(C/C++での自動または自動など)の説明に限定され、オブジェクト/配列については説明しません。

そのような自動変数の実際のサイズはほとんど問題になりません(たとえば、パフォーマンスまたはスペース)。

これは、基盤となるハードウェアCPUが1ビットではなく、より大きなビットサイズ(32や64など)でより自然に機能するためです。 8ビットまたは16ビットのサイズでさえ一般的に32より速くなく、ハードウェア命令セットのより広いレジスタで動作するために、8ビットの処理には追加の命令が1つまたは2つ必要になる場合があります。

そして、もう1つの理由は、ローカル変数の使用が制限されていることです。これらはコードによって直接使用され、コードによってのみ使用されるため、特にスケーリングの問題の影響を受けません。特に、潜在的に任意のスケールのデータ構造によって使用されるオブジェクトや配列と比較して。

(再帰をローカル変数のスケーリングと見なす可能性があるため、再帰ルーチンのローカル変数が大きいほど、スタックオーバーフローのリスクが高くなります。)

ただし、インスタンスの数が多い場合、オブジェクトのサイズは非常に重要になる可能性があります。また、要素の数が多い場合は、配列要素のサイズも重要になる可能性があります。


バイト/文字/短いプリミティバのデータ型でもサイズが8/16/16ビットとして定義されていますが、32ビットを使用することを意味しますか?

地元の人にとっては、おそらく、JITに依存しないかもしれません。

オブジェクトの場合、JVMバイトコードおよびクラスファイルメカニズム内では、フィールドはIDによって直接アクセスされ、「セル」という概念はありませんが、(ローカルおよびパラメーター)変数にはあります。

JVMの実装(JITを含む)は、実装内(マシンコードレベルなど)でフィールドの順序を再配置できる柔軟性を備えているため、2つの16ビットフィールドは、ソースコードで隣接して宣言されていなくても、同じ32ビットWordを占有できます。 ;これにより、位置合わせを維持するために必要なパディングによって生じるオーバーヘッドが削減されます。このような配置、パディング、フィールド配置も、JVM交換形式の問題ではなく、JVM実装固有のものです。理論的には、JITはブール値を配列で1ビットにパックするか、8つの個別のブール値フィールドをオブジェクトの1バイトにパックすることができます。そのほとんどは、JVM実装の選択ではありません。

8
Erik Eidt