2008-09-16 10 views
4

javaのintの配列は、32ビット値のブロックとしてメモリに格納されます。 Integerオブジェクトの配列はどのように格納されていますか?即ち整数配列は内部的にJVMに格納されますか?

int[] vs. Integer[] 

iは整数配列の各要素は、Integerオブジェクトへの参照であることを想像するだろう、とIntegerオブジェクトがちょうど他のオブジェクトのようなオブジェクト・ストレージ・オーバーヘッドを有すること。

しかし、Integersは不変であり、intの配列のように格納するので、JVMはいくつかの巧妙な賢さを願っています。

私の希望は悲観的に素朴ですか?最後のパフォーマンスが重要なアプリケーションでは、Integer配列はint配列よりもはるかに遅いのですか?

答えて

11

ないVMは、私は次のような理由のためのint []配列のような整数[]配列を格納するのを知っている:

  1. あり、アレイ内のヌル Integerオブジェクトも、あなたは何ビットが残っていないことができますこれをint配列で示すために使用します。VMは、隠されたビット配列内のアレイスロットごとにこの1ビット情報を格納することができる。
  2. Integer配列の要素を同期させることができます。これは、最初のポイントとして克服するのがずっと難しくなります。なぜなら、各アレイスロットに対してモニターオブジェクトを保存する必要があるからです。
  3. Integer []の要素は、同一性を比較することができます。たとえば、newを使って1の値を持つ2つのIntegerオブジェクトを作成し、異なる配列スロットに格納し、後でそれらを取り出して==で比較することができます。これは偽につながるはずなので、この情報をどこかに保存する必要があります。または、Integerオブジェクトのいずれかへの参照をどこかに保持し、これを比較のために使用し、==比較の1つが偽であり、かつ真であることを確認する必要があります。つまり、 Integer配列では、オブジェクトアイデンティティー全体の概念が静かに扱いにくいということです。
  4. Integer []を例えばにキャストすることができます。 Object []を呼び出し、Object []だけを待つメソッドに渡します。これは、Object []を扱うすべてのコードが特別なInteger []オブジェクトを処理できるようになったことを意味します。アカウントにこのすべてを取る

、おそらくナイーブ実装と比較していくつかのスペースを節約し、特殊な整数[]を作成することが可能であろうが、追加の複雑さは、おそらく他の多くのコードに影響を与えます最終的には遅くなります。

int []の代わりにInteger []を使用するオーバーヘッドは、スペースと時間が大幅に大きくなることはありません。典型的な32ビットVMでは、Integer []がint []と同じくらいのスペースを使用している間、Integerオブジェクトは16バイト(オブジェクトヘッダーの場合は8バイト、ペイロードの場合は4つ、配置の場合は4つの追加バイト)を消費します。 64ビットVM(64ビットポインタを使用していますが、必ずしもそうであるとは限りません)では、Integerオブジェクトは24バイト(ヘッダーは16、ペイロードは4、アラインメントは4)を消費します。さらに、Integer []のスロットはint []のように4ではなく8バイトを使用します。これは、スロット当たりの16〜28バイトのオーバーヘッドを期待できることを意味し、プレーンint配列と比較しての因数は4〜7です。

パフォーマンスのオーバーヘッドは、主に二つの理由から、あまりにも重要になります:あなたはより多くのメモリを使用するので

  1. 、あなたは、メモリ・サブシステム上でより多くの圧力をかける場合にはキャッシュミスを持っている可能性が高くなって整数[]の。たとえば、int []の内容を線形にトラバースすると、(レイアウトも線形であるため)キャッシュは必要なときにほとんどのエントリを取得します。 Integer配列の場合、Integerオブジェクト自体がヒープ内にランダムに散在しているため、次のメモリ参照が指し示す場所をキャッシュが推測するのが難しくなります。
  2. ガベージコレクションは、使用されるメモリが増え、各Integerオブジェクトを個別にスキャンして移動する必要があるため、はるかに多くの作業を必要とします。int []の場合、オブジェクトは1つだけでオブジェクトの内容スキャンする必要はありません(他のオブジェクトへの参照は含まれていません)。

は、現在のVMでの整数配列を使用するよりも効率的でより速く、メモリになりますint型[]パフォーマンスの重要な仕事を使用して、それを要約すると、これが近い将来にあまり変化しますそうです。

1

私はあなたの希望が悲惨であると思います。具体的には、Integerは潜在的にnullになる可能性がありますが、intは不可能であるという問題に対処する必要があります。それだけで、オブジェクトポインタを格納するのに十分な理由があります。つまり、実際のオブジェクトポインタは不変のintインスタンスになります。特に整数の一部を選択したものです。

0

Integer []はエントリとして "null"を受け入れる必要があり、int []はそうでなければならないため、Integer []があってもある程度の簿記が必要です。 int []によってサポートされています。

intはできないのに対し、整数、nullになることを理由ユーザーはint []

0

、パフォーマンスの問題のすべての最後のオンス場合整数は、そのオーバーヘッドの全てで、本格的なJavaオブジェクトであるため、だから、あります含まれています。あなたはそのfooが値を持つことになります言って良いです

Integer foo = new Integer(); 
foo = null; 

を書くことができますが、それはまだいないので、この中に値があります。

もう1つの違いは、intがオーバーフロー計算を実行しないことです。例えば、

int bar = Integer.MAX_VALUE; 
bar++; 

は陽気バーをインクリメントし、あなたは、あなたが最初の場所で意図したもので、おそらくではありません非常に負の数、で終わります。

foo = Integer.MAX_VALUE; 
foo++; 

私はよりよい行動であると思います。

最後に、IntegerはJavaオブジェクトであり、オブジェクトのスペースオーバーヘッドを持ちます。他の誰かがここでチャイムする必要があるかもしれないと思うが、私はすべてのオブジェクトがオーバーヘッドのために12バイトを消費し、次にデータストレージ自体のためのスペースを消費すると信じている。パフォーマンスとスペースの後にいるなら、Integerが適切なソリューションかどうか疑問に思う。

3

John Roseがこの問題を解決するためにJVMでfixnumsに取り組んでいます。

関連する問題