web-dev-qa-db-ja.com

Javaのブールプリミティブサイズが定義されていないのはなぜですか?

Java Virtual Machine Specification は、ブールprimitive型のサポートが制限されていることを示しています。

Javaブール値の操作専用の仮想マシン命令はありません。代わりに、Javaブール値を操作するプログラミング言語の式は、 Java仮想マシンのintデータ型の値。

上記は、ブール値を操作するときにintデータ型が使用されることを(私は誤って解釈したかもしれませんが)意味しますが、これは32ビットのメモリ構造です。ブール値が1ビットの情報のみを表す場合:

  • 整数ではなくブールのプロキシとしてバイトまたはショートタイプが使用されないのはなぜですか?
  • どのようなJVMでも、ブール型を格納するために使用されているメモリ量を正確に調べる最も信頼できる方法は何ですか?
107
Joel

簡単な答え:はい、ブール値は32ビットエンティティとして操作されますが、ブール値の配列は要素ごとに1バイトを使用します。

より長い答え:JVMは、ローカル変数、メソッド引数、および式の値を保持するために使用される32ビットスタックセルを使用します。 1セルより小さいプリミティブはパディングされ、32ビットより大きい(ロングおよびダブル)プリミティブは2セルを使用します。この手法により、オペコードの数は最小限に抑えられますが、いくつかの特有の副作用(バイトをマスクする必要性など)があります。

配列に格納されているプリミティブは32ビット未満を使用する場合があり、配列からプリミティブ値をロードおよび格納するための異なるオペコードがあります。ブール値とバイト値は両方ともbaloadおよびbastoreオペコードを使用します。これは、ブール配列が要素ごとに1バイトを使用することを意味します。

インメモリオブジェクトレイアウトに関する限り、これは「プライベート実装」でカバーされます rules 、1ビット、1バイト、または別のポスターに記載されているように、64ビットのdouble -単語の境界。ほとんどの場合、基礎となるハードウェアの基本的なWordサイズ(32または64ビット)が必要です。


ブール値が使用するスペースの量を最小限に抑える限り、それは実際にはほとんどのアプリケーションにとって問題ではありません。スタックフレーム(ローカル変数とメソッド引数を保持する)はそれほど大きくなく、大きなスキームでは、オブジェクトの離散ブール値もそれほど大きくありません。多数のブール値を持つオブジェクトが多数ある場合は、ゲッターとセッターを介して管理されるビットフィールドを使用できます。ただし、メモリ時間のペナルティよりもおそらく大きいCPU時間のペナルティを支払うことになります。

112
kdgregory

継承階層のどこかにある単一のブール値は、最大8バイトを使用できます。これはパディングが原因です。詳細は my Java object?)で使用されるメモリ量 :にあります。

ブールがどれだけ消費するかという質問に戻って、はい、少なくとも1バイトを消費しますが、アライメントルールのために、さらに多くを消費する可能性があります。私見では、boolean []がエントリごとに1ビットではなく1バイトを消費し、さらに配列のサイズフィールドのアライメントのためにオーバーヘッドを消費することを知ることはより興味深いです。大きなフィールドのビットが有用なグラフアルゴリズムがあり、boolean []を使用する場合、実際に必要なメモリのほぼ8倍のメモリが必要であることに注意する必要があります(1バイト対1ビット)。

7
akuhn

Java in a Nutshell(O'Reilly)の第5版では、ブールプリミティブ型は1バイトです。ヒープの検査が示しているものに基づいて、それは間違っている可能性があります。ほとんどのJVMが変数に1バイト未満を割り当てることに問題があるのではないかと思います。

5
Matthew Flynn

ブールマッピングは、32ビットCPUを念頭に置いて行われました。 int値は32ビットであるため、1回の操作で処理できます。

ここに Peter NorvigのJava IAQ:よくある質問に答える からの解決策があります(サイズに多少の不正確さはあります):

static Runtime runtime = Runtime.getRuntime();
...
long start, end;
Object obj;
runtime.gc();
start = runtime.freememory();
obj = new Object(); // Or whatever you want to look at
end =  runtime.freememory();
System.out.println("That took " + (start-end) + " bytes.");
3
Thomas Jung

CPUは特定のデータ型の長さで動作します。 32ビットCPUの場合、それらは32ビット長であるため、Javaで「int」と呼ばれます。 CPUが処理できるようになる前に、この長さ以下またはそれ以上をすべて埋めるか、この長さに分割する必要があります。これにはそれほど時間はかかりませんが、基本操作に1ではなく2 CPUサイクルが必要な場合、これはコスト/時間を2倍にすることを意味します。

この仕様は32ビットCPU専用であるため、ネイティブデータ型でブール値を処理できます。

ここには1つしかありません。速度またはメモリ-Sunは速度を決定しました。

2
Hardcoded

ブールは1ビットの情報を表しますが、その「サイズ」は正確に定義されたものではありません。たとえば、Sun Javaチュートリアル。ブールリテラルには、trueとfalseの2つの値しかありません。 Javaデータ型 詳細については。

1
Krishan