離れていくためにいくつかの概念があります:
- テキストプログラミング言語である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実装の選択ではありません。