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


10

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

正確に定義されていない

さらに説明すると

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

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

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

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

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

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



Does it mean even byte/char/short primitiva data types also take 32 bit though their size is defined as 8/16/16 bit ? - はい。
ロバートハーベイ

Also can we say boolean size will be 32 bit on 32 bit cpu and 64 bit on 64 bit cpu ?-いいえ。サイズはJVMによって定義されます。
ロバートハーベイ

@RobertHarveyバイト/文字/短いプリミティブデータ型も32ビットを取る場合、Javaでそれらのサイズを8/16/16ビットとして定義する意味は何ですか?
user3222249 2018年

そのため、配列により効率的に格納できます。
Robert Harvey

回答:


11

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

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

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

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


ロバートとあなたが間接的に言ったように、バイト/文字/ショートプリミティブデータ型も32ビットを取る場合、私の質問は、Javaでそれらのサイズを8/16/16ビットとして定義するポイントは何ですか?
user3222249 2018年

それらの制限された値の範囲(または、必要に応じて「サイズ」)を定義するポイントは、それらのセマンティクス(例:127から-128への折り返し)です。多くの場合、それは望ましくありませんが、場合によっては役立ちます。そして、より短い型の配列があり、それらは本当にint配列よりも少ないスペースを占有します。そして最後に、スペースを4バイト未満に最適化するJITコンパイラー/ HotSpotエンジンの可能性があります。
ラルフクレバーホフ2018年

8

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

  • テキストプログラミング言語であるJavaプログラミング言語自体
  • Java仮想マシンのバイトコードとクラスファイル形式。これは、元のJava言語ソースコードのバイナリコンパイルされたエンコードであり、Javaオブジェクトコードを格納、ロード、および共有するための交換ファイル形式として使用されます。
  • 特定のJava仮想マシンの実装。これはインタープリターになることもありますが、多くの場合、代わりにJITベースの実装です。
  • JITは、ハードウェアプロセッサで直接実行されるマシンコードを生成しました。

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

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

言語はオブジェクトのサイズへの問い合わせを可能にする計測機能を定義しますが、(1)これは計測を必要とし、(2)推定のみを提供し、(3)この問い合わせはプリミティブ型またはローカル変数には適用されません。

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

パディング引用は、(Java言語やJVM実装とは異なり)交換メカニズムとして使用されている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ビットワードを占有できます。 ; これにより、位置合わせを維持するために必要なパディングによって生じるオーバーヘッドが削減されます。このような配置、パディング、フィールド配置も、JVM交換形式の問題ではなく、JVM実装固有のものです。理論的には、JITはブール値を配列の1ビットにパックするか、8つの個別のブール値フィールドをオブジェクトの1バイトにパックすることができます。そのほとんどは、JVM実装の選択ではありません。

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