現在、メモリ消費を最小限に抑えようとしているデータ構造を設計しています。トライ内のノードの配置によっては、null になるインスタンス変数がいくつかあります。null参照で大量のスペースを無駄にしないように、別々のクラス(インスタンス変数を持つクラスと持たないクラス)を作成する道をたどり始めました...しかし、jvmがどのように機能するのか疑問に思い始めました. オブジェクト参照が null の場合でも、完全な 8 バイト (x64 アーキテクチャを想定) を使い果たしますか? または null 参照を格納するためのより最適な方法がありますか?
4 に答える
JVMは、他のJVMと同じくらい多くのスペースをnull
参照に使用するとほぼ確信しています。たとえば3つの参照フィールドを持つオブジェクトがあり、中央のオブジェクトをnullにすると、仮想マシンは3番目のオブジェクトを移動して、4バイトまたは8バイトを節約できるとは思いません(変更した場合)。他のnull
何かに、それはものを再び動かさなければならないでしょう)。これが技術的に実現可能である場合、それは価値がありません-余分な計算コストとコードの複雑さは潜在的な利益を殺します。また、Cの遺産もあり、ほとんどのマシンでは、ビット単位で0に等しいポインターは、非常に低いレベルでNULLとして機能するため、null
参照はかなり明白な表現になります。
Oracle / Sun JDKでは、ヒープが16 GBより小さい場合(参照の有無に関係なく)、- XX:+ UseCompressedOopsnull
コマンドライン引数を使用して、64ビットでは8バイトではなく4バイトを参照できます。
答えはイエスです。それでも必要なバイトを使用します。Java では、null は参照が持つことができる単なる値です。これは、参照が何も参照していないことを意味します。この場合、参照のためにスペースを消費します。これは、32 ビット システムでは 4 バイト、64 ビット システムでは 8 バイトです。
null 変数はメモリにスペースを必要としますか?を参照してください
クラスとスーパークラスもいくつかのバイトを使用します。
ほとんどのメモリ使用を本当に避けたい場合は、FlyWeightパターンを使用することをお勧めします
(アイデア:同じ不変オブジェクトを再利用します;それらを作成してキャッシュするファクトリがあります)。
あなたのコードはもう少し複雑になります、それは悪いことです。しかし、メモリを大幅に節約できます。
もう1つの選択肢は、(オブジェクトではなく)より単純なタイプで作業することです。しかし、それはあまり実用的ではありません、あなたはあなたのデータに対して外部的にすべてをしなければなりません...それで私はFlyWeightを好みます。
簡単な数学を適用できます: type のフィールドを持つオブジェクトがあると仮定します。int
これは、任意のアーキテクチャで 4 バイトであり、未定義である可能性があります (未定義であることを理解できるフィールドの値はユースケースによって異なります)。現在、定義されている場合は、4 バイトを使用します。定義されていない場合は、4 バイトが無駄になります。
それをオブジェクトにラップするとします。これで、フィールドが定義されている場合、ポインターに 4 または 8 バイトが使用されます (JVM のビット数と でオンまたはオフにされたポインター圧縮に応じて-XX:+UseCompressedOops
)。単一の 4 バイト フィールドを持つオブジェクトは、ビット数に関係なく 16 バイトを消費します (オブジェクトは、32 ビットと 64 ビットの両方の Java ランタイムで 16 バイトを占有します。これは、8 または 12 バイトのオブジェクト ヘッダーと 4 バイトの値が含まれ、使用メモリが整列されるためです。最も近い 8 バイト)。
要約すると、プリミティブに固執する場合は 4 バイトを使用します。シングルint
をオブジェクトにラップする場合、フィールドに値がある場合は 20 または 24 バイトを使用します。値が null の場合は 4 または 8 バイト。