重複の可能性:
Javaメモリでnullとは正確には何ですか
オブジェクトなどのメモリでnull値がどのように表現されるかを知っている人はいますか? ドット ネットでは、null インジケータのブール値と対応する型の値で表されます (参照はこちら)。それで、Javaでそれがどのように行われるか知っている人はいますか??
重複の可能性:
Javaメモリでnullとは正確には何ですか
オブジェクトなどのメモリでnull値がどのように表現されるかを知っている人はいますか? ドット ネットでは、null インジケータのブール値と対応する型の値で表されます (参照はこちら)。それで、Javaでそれがどのように行われるか知っている人はいますか??
Java 仮想マシンの仕様では、null をエンコードする具体的な値は必須ではありません。
したがって、何でもかまいませんが、すべてゼロの参照値である可能性が非常に高くなります。参照自体は単純なポインタ (つまり、アーキテクチャに適したサイズのネイティブ ポインタと同様の単なる仮想アドレス) にすることができますが、そうである必要はありません。一部の JVM は、参照を処理する非常にスマートな方法を備えています。たとえば、Hotspot は、x64 プロセスで実行されている場合でも、多くの状況で参照に 32 ビット値を使用できます。
理論的にはJVMシークレットであり、実際には32ビンVMでは0(0x00000000)です。Oracle JVMを使用する場合は、任意のアドレスのメモリコンテンツを読み取ることができるsun.misc.Unsafeを使用して検証できます。
public class Test {
int i1 = 100;
String s = null;
int i2 = 200;
public static void main(String[] args) throws Exception {
Test test = new Test();
System.out.println(getInt(test, "i1"));
System.out.println(getInt(test, "s"));
System.out.println(getInt(test, "i2"));
}
static int getInt(Test test, String name) throws Exception {
Unsafe u = getUnsafe();
long offset = u.objectFieldOffset(Test.class.getDeclaredField(name));
return u.getInt(test, offset);
}
static Unsafe getUnsafe() throws Exception {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
return (Unsafe) f.get(null);
}
}
出力
100
0
200
null は実際には有効なオブジェクト インスタンスではないため、null 自体にメモリを割り当てる必要はありません。これは、オブジェクト参照が現在オブジェクトを参照していないことを示す単なるプレースホルダーです。
次のようなことをすると:
文字列 str = null;
割り当てられる唯一のものは、文字列への参照です (これは、ポインター型を含む言語の文字列ポインターに似ています)。この参照は 32 ビットまたは 64 ビットの変数 (ハードウェア アーキテクチャと Java のバージョンによって異なります) であり、スタック上に存在します (おそらく、宣言が配置される正確なコンテキストによって異なります)。
正確な表現は指定されていません0x0
が、他の C のような言語と同じだと思います。これは、追加のフィールドや追加の情報ではなく、他の方法では発生しない特別な値です。
注: がある場合、String
それはオブジェクトではなく参照です。この 4 バイトの値はオブジェクトを参照できますが、その場合はnull
有効なオブジェクトではない値です。
ところで: ほとんどの 64 ビット JVM は、ヒープが 32 GB 以上でない限り、32 ビット参照を使用します。すべてのオブジェクトが 8 バイト (または 16 バイト) で整列されているため、これは OpenJDK JVM で可能です。下位 3 ビットまたは 4 ビットは常に 0 であるため、アドレス範囲を通常の 4 GB 範囲の 8 倍または 16 倍に拡張して格納する必要はありません。