17

ボックス化されたプリミティブは、Java のようにjava.lang.Integer、またはjava.lang.CharacterJava でどのくらいの大きさですか?

Anintは 4 バイトで、通常のポインターも 4 バイトです (JVM によって圧縮されていない場合)。したがって、整数 (キャッシュなし) のコストは4 bytes + 4 bytes = 8 bytes? ボックス オブジェクト内に非表示のフィールドが他にないか、またはオブジェクトに関して追加のオーバーヘッドが発生していませんか (つまり、私が認識していないオブジェクトの一般的なコストはありますか?)。

キャッシングの問題には興味がありません。特定の範囲内の整数が JVM によってキャッシュされることを知っています。

質問を言い換えることができます:ボックス化された値とプリミティブ値に使用されるメモリの量に乗算される最大係数は何ですか?

編集: JVM の複数の実装が存在することは理解しています。典型的な 32 ビット HotSpot 実装の典型的なコストは?

4

4 に答える 4

9

これは実装定義であるため、具体的な答えはありません。でもホットスポットなら答えられるはず。

知っておく必要があるのは、Hotspot は常にオブジェクトを 8 バイト境界に整列させるということです。さらに、オブジェクトごとに 2 ワードのオーバーヘッドがあります。[1]

これをまとめると、次のようになります。

32 ビット VM: 4 バイトの整数 + 2 ワードのオブジェクト ヘッダー = 12 バイト。これは 8 の倍数ではないため、1 つの整数のコストは次の 8 の倍数である 16 バイトになります。

64 ビット VM: 4 バイト整数 + 2 ワード = 20 バイト。再び切り上げ: 24 バイト サイズ。

単純な int ラッパーの場合ではない他のオブジェクトへの参照がある場合を除いて、参照のサイズは明らかにオブジェクト自体のサイズには影響しません。もしそうなら、32ビットの場合は参照ごとに4バイト、ヒープの場合は4バイト<= 32GBでCompressedOops、最新のJVMでは64ビットJVMの場合(それ以外の場合は8バイト)になります。

[1] 興味のある方は以下のコードをご覧くださいshare/vm/oops/oop.hpp

于 2012-01-27T17:55:59.040 に答える
1

それ以上です。

すべてのオブジェクト参照には、クラス参照などの追加のオーバーヘッドがあります。それだけでなく、4 バイトのポインターは正確ではありません。これは参照であるため、ID とポインターであり、64 ビット JVM を使用している場合、そのポインターは 8 バイトになる可能性があります。

VM の実装にも違いがあるようです。これを確認する最善の方法は、プロファイラーでプルアップすることです。

私の(スーパーSWAG)の見積もりはそうです。オブジェクト参照 16 バイト (64 ビット JVM) クラス参照 16 バイト プリミティブ値 4 バイト (int と仮定) 合計。36 バイト。

編集: 32 ビット JVM を指定したので、上記と同じ計算を使用すると、私の SWAG は 20 バイトになります。

于 2012-01-27T17:38:52.123 に答える
0

これは、ボックス化されたプリミティブのストレージ コストに関するあなたの質問に正確に答えるものではないことはわかっていますが、あなたの質問から、それらの使用が保証されているかどうか疑問に思っていることがわかります。

Joshua Bloch による「Effective Java (2nd Edition)」からの抜粋を次に示します。

"So when should you use boxed primitives? They have several legitimate uses. The first is as elements, keys, and values in collections. You can’t put primitives in collections, so you’re forced to use boxed primitives. This is a special case of a more general one. You must use boxed primitives as type parameters in parame- terized types (Chapter 5), because the language does not permit you to use primi- tives. For example, you cannot declare a variable to be of type Thread- Local<int>, so you must use ThreadLocal<Integer> instead. Finally, you must use boxed primitives when making reflective method invocations (Item 53).

In summary, use primitives in preference to boxed primitives whenever you have the choice. Primitive types are simpler and faster. If you must use boxed primitives, be careful! Autoboxing reduces the verbosity, but not the danger, of using boxed primitives. When your program compares two boxed primitives with the == operator, it does an identity comparison, which is almost certainly not what you want. When your program does mixed-type computations involving boxed and unboxed primitives, it does unboxing, and when your program does unboxing, it can throw a NullPointerException. Finally, when your program boxes primitive values, it can result in costly and unnecessary object creations."

それが役立つことを願っています。

于 2012-01-27T18:03:30.053 に答える