Java のオブジェクトのメモリ使用量を理解しようとしています。Javaのオブジェクトとメモリに関するこれと他のドキュメントを読みました。
ただし、sizeof Java ライブラリまたは visualvm を使用している場合、2 つの異なる結果が得られますが、前の参照 ( http://www.javamex.com ) によると、どちらも期待できるものではありません。
私のテストでは、Java SE 7 Developer Preview
on64-bits Mac
とjava.sizeof 0.2.1
を使用していvisualvm 1.3.5
ます。
TestObject
、、、の 3 つのクラスがTestObject2
ありTestObject3
ます。
public class TestObject
{
}
public class TestObject2 extends TestObject
{
int a = 3;
}
public class TestObject3 extends TestObject2
{
int b = 4;
int c = 5;
}
私の主なクラス:
public class memoryTester
{
public static void main(String[] args) throws Throwable
{
TestObject object1 = new TestObject();
TestObject2 object2 = new TestObject2();
TestObject3 object3 = new TestObject3();
int sum = object2.a + object3.b + object3.c;
System.out.println(sum);
SizeOf.turnOnDebug();
System.out.println(SizeOf.humanReadable(SizeOf.deepSizeOf(object1)));
System.out.println(SizeOf.humanReadable(SizeOf.deepSizeOf(object2)));
System.out.println(SizeOf.humanReadable(SizeOf.deepSizeOf(object3)));
}
}
java.SizeOf() を使用すると、次のようになります。
{ test.TestObject
} size = 16.0b
16.0b
{ test.TestObject2
a = 3
} size = 16.0b
16.0b
{ test.TestObject3
b = 4
c = 5
} size = 24.0b
24.0b
私が持っているvisualvmで:
this (Java frame) TestObject #1 16
this (Java frame) TestObject2 #1 20
this (Java frame) TestObject3 #1 28
インターネットで読んだドキュメントによると、私は 64 ビットなので、16 バイトのオブジェクト ヘッダーが必要ですTestObject
。
次にTestObject2
、整数フィールドに 4 バイトを追加して 20 バイトにする必要があるため、4 バイトのパディングを再度追加して、合計サイズを 24 バイトにする必要がありTestObject2
ます。私が間違っている?
についてもTestObject3
同様に、2 つの整数フィールドにさらに 8 バイトを追加する必要があります。これは 32 バイトになるはずです。
VisualVm はパディングを無視するようですが、java.sizeOf はオブジェクト ヘッダーに含まれているかのように 4 バイトを欠いているようです。整数を 4 つのブール値に置き換えると、同じ結果が得られます。
質問:
これら 2 つのツールで異なる結果が得られるのはなぜですか?
パディングが必要ですか?
また、クラスとそのサブクラスの間にパディングがある可能性があることをどこかで読みました(リンクが見つかりませんでした)、そうですか?その場合、継承されたクラスのツリーにメモリのオーバーヘッドが発生する可能性がありますか?
最後に、Java が行っていることの詳細を示す Java 仕様/ドキュメントはありますか?
ご協力いただきありがとうございます。
アップデート:
utapyngo のコメントに答えるために、visualvm のオブジェクトのサイズを取得するために、heapdump を作成し、「クラス」の部分で、「インスタンス」列の次の「サイズ」列を確認します。オブジェクトの種類ごとに 1 の場合のインスタンスの数。
Nathaniel Ford のコメントに答えるために、各フィールドを初期化し、メインメソッドでそれらを使用して単純な合計を計算しました。結果は変わりませんでした。