可能重复:
Java 内存中究竟是什么 null
有谁知道一个对象或任何东西的内存中的空值是如何表示的。在 dot net 中,它由空指示符布尔值和相应类型的值表示(请参阅此处)。那么有人知道它是如何在java中完成的吗?
可能重复:
Java 内存中究竟是什么 null
有谁知道一个对象或任何东西的内存中的空值是如何表示的。在 dot net 中,它由空指示符布尔值和相应类型的值表示(请参阅此处)。那么有人知道它是如何在java中完成的吗?
Java 虚拟机规范不要求使用具体的值编码 null。
所以它可以是任何东西,但它很可能是一个全为零的参考值。引用本身可以是简单的指针(即只是一个与本机指针相同的虚拟地址,具有适合体系结构的大小),但也不必如此。一些 JVM 有非常聪明的方法来处理引用——例如,Hotspot能够在许多情况下使用 32 位值作为引用,即使在 x64 进程中运行时也是如此。
理论上它是 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
没有指定确切的表示,但我认为它0x0
就像在其他类似 C 的语言上一样。它是一个特殊值,否则不会出现,而不是附加字段或额外信息。
注意:当你有它时,String
它是一个引用而不是一个对象。这个 4 字节的值可以引用一个对象,或者在 的情况下null
是一个不是有效对象的值。
顺便说一句:大多数 64 位 JVM 使用 32 位引用,除非堆为 32 GB 或更多。这在 OpenJDK JVM 中是可能的,因为所有对象都是 8 字节(或 16 字节)对齐的。由于低 3 位或 4 位始终为 0,因此不需要将地址范围扩展为典型 4 GB 范围的 8 倍或 16 倍。
不应为 null 本身分配内存,因为 null 实际上不是有效的对象实例。它只是一个占位符,指示对象引用当前未引用对象。
当您执行以下操作时:
字符串 str = null;
唯一分配的是对字符串的引用(这类似于包含指针类型的语言中的字符串指针)。此引用是一个 32 位或 64 位变量(取决于您的硬件架构和 Java 版本),它驻留在堆栈中(可能取决于放置声明的确切上下文)。