可能是重复内容:
Java中null在内存中到底是什么
有人知道在对象或其他情况下,如何在内存中表示空值吗?在dot net中,它由空指示器布尔值和相应类型的值表示(参见此处)。那么有人知道在Java中是如何实现的吗?
可能是重复内容:
Java中null在内存中到底是什么
有人知道在对象或其他情况下,如何在内存中表示空值吗?在dot net中,它由空指示器布尔值和相应类型的值表示(参见此处)。那么有人知道在Java中是如何实现的吗?
理论上,它是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
确切的表示方式未指定,但我认为它只是像其他类C语言一样的0x0
。这是一个特殊的值,否则不会出现,不是额外的字段或额外的信息。
注意:当您有一个String
时,它是一个引用而不是一个对象。这个4字节的值可以引用一个对象,或者在null
的情况下是一个无效的对象。
顺便说一下:大多数64位JVM使用32位引用,除非堆大小为32 GB或更大。这在OpenJDK JVM中是可能的,因为所有对象都是8字节(或16字节)对齐的。由于较低的3或4位始终为0,它们不需要被存储,将地址范围扩展了8倍或16倍的典型4 GB范围。
不应为 null 本身分配任何内存,因为 null 实际上不是一个有效的对象实例。它只是一个占位符,表示对象引用当前未指向对象。
当您执行以下操作时:
String str = null;
唯一分配的是对字符串的引用(这类似于包含指针类型的语言中的字符串指针)。此引用是一个32位或64位变量(取决于您的硬件架构和Java版本),它驻留在堆栈上(可能取决于声明所处的确切上下文)。
Nullable<T>
而不是空引用。 - Jon Skeet