5

オブジェクトのメモリに割り当てられた実際のスペースを正確に知りたいです。

いくつかの例で説明しようとします.64ビットJVMを使用すると、ポインタサイズは8バイトになるはずです:

  • Object singletest = new Object();オブジェクトを参照するには、オブジェクトのサイズに加えて 8 バイトが必要です。
  • Object arraytest = new Object[10];配列が格納されている位置を参照するために 8 バイト、配列を格納するために 8*10 バイト、および各オブジェクトのサイズが必要です。
  • int singleint = new int;int はプリミティブ型であるため、わずか 2 バイトで済みます。
  • int[] arrayint = new int[10];位置を参照するには 8 バイト、要素には 10*2 バイトが必要です。

さらに、これが Java で次のようなコードを記述できる理由です。

int[][] doublearray = new int[2][];
int[0][] = new int[5];
int[1][] = new int[10];

実際に起こることは、配列がオブジェクトのような参照 (別名ポインター) を生成するため、宣言時の 2 番目の次元のサイズは実際には問題になりません (次元は異なる場合があり、それらの間にリンクはありません)。次に、使用されるスペースは次のようになります: doublearrayへの参照(8 バイト)、最初の次元は単に 2 番目の次元への参照であるため、他の 8 バイト * 2 (最初の次元のサイズ)、そして最後に 2 バイト * 5 に 2 バイト * 10 を加えたものになります。 .

最後に、次のような実際のクラスがあるとします。

class Test {
   int a, b;
   int getA() {return A};
   void setA(int a) {this.a = a;}
   int getB() {return B};
   void setB(int b) {this.b = b;}
}

インスタンス化するために new を呼び出すと、整数をクラスに格納するために 8 バイトのポインター (または Java であるため参照という名前) と 2 + 2 バイトが使用されます。

質問は次のとおりです。私は正しいですか、それともまったくナンセンスを書きましたか? さらに、オブジェクトをインスタンス化せずに宣言しただけの場合、8 バイトが割り当てられて使用されますか? null 値を代入するとどうなるでしょうか。

一方、プリミティブ型の場合、宣言するだけで要求されたスペースが割り当てられると確信しています(「int i」を宣言すると、参照が使用されず、メモリの一部だけが「0」に設定されるため、すぐに i++ を呼び出すことができます)。

私は巧妙な応答なしにインターネットで検索しました...私はたくさんの質問を書いたことを知っていますが、どんな助けも大歓迎です! (興味があるのは私だけではないかもしれません)

4

1 に答える 1

10

64 ビット JVM を使用する場合、ポインターのサイズは 8 バイトにする必要があります。

実際には、最大ヒープ サイズが 32 GB 以上でない限り、通常は 32 ビットです。これは、Java がポインターではなく参照を使用するためです (各オブジェクトは 1 境界ではなく 8 バイト上にあります)。

JVM は、使用する JVM と最大ヒープ サイズに応じて参照のサイズを変更できます。

Object singletest = new Object(); オブジェクトを参照するのに 8 バイトとオブジェクトのサイズを足す必要があります。

オブジェクトは約 16 バイトのヒープを使用します。4 バイトのスタックを使用する場合と使用しない場合がありますが、レジスタのみを使用することもできます。

オブジェクト arraytest = 新しいオブジェクト[10];

これは、ヘッダーに約 16 バイト、さらに参照サイズの 10 倍 (合計で約 56 バイト) を使用します。

int singleint = 新しい int; int はプリミティブ型であるため、わずか 2 バイトで済みます。

intnew常に 32 ビット ビットであるため、プリミティブを作成することはできません。概念的にはスタック上にあるため、4 バイトのスタックを使用するか、レジスタのみを使用する場合があります。

int[] arrayint = 新しい int[10]; 位置を参照するには 8 バイト、要素には 10*2 バイトが必要です。

new Object[10]この場合も、オブジェクトは(56 バイト)と同じサイズになる可能性があります。

int[][] doublearray = new int[2][];
int[0][] = new int[5];
int[1][] = new int[10];

混同される可能性があるため、 doublearray とは呼びませんdouble[]

ただし、サイズは、約 16 + 2 * 4doublearrayおよび 16 + 5*4 + 4 (パディング用) および 16 + 10 * 4 になる可能性があります。

ヒープに割り当てられたメモリは、8 バイト境界に配置されます。

インスタンス化するために new を呼び出します。8 バイトのポインター (または Java であるため、参照という名前) に加えて、整数をクラスに格納するために 2 + 2 バイトが使用されます。

参照はスタック上にあり、通常は含まれません。

オブジェクトには約 16 バイトのヘッダーがあり、int 値は 2 * 4 バイトを占めます。

オブジェクトをインスタンス化せずに宣言するだけの場合

Java ではオブジェクトを宣言できず、プリミティブと参照のみを宣言できます。

null 値を代入するとどうなりますか?

これにより参照の値が変更される可能性がありますが、それ以外の場合は何も起こりません。

「int i」を宣言すると、参照が使用されず、メモリの一部だけが「0」に設定されるため、すぐに i++ を呼び出すことができます。

ヒープは使用されず、おそらくスタックも使用されません (おそらく 4 バイト)。何もしない場合、JITコンパイラがコードを削除する可能性があります。

興味があるのは私だけではないかもしれません

...しかし、尋ねることを恐れませんでした。;)

于 2012-04-30T16:01:39.553 に答える