6

可能重复:
Java 内存中究竟是什么 null

有谁知道一个对象或任何东西的内存中的空值是如何表示的。在 dot net 中,它由空指示符布尔值和相应类型的值表示(请参阅此处)。那么有人知道它是如何在java中完成的吗?

4

4 回答 4

9

来自JVM 规范,第 2.4 节

Java 虚拟机规范不要求使用具体的值编码 null。

所以它可以是任何东西,但它很可能是一个全为零的参考值。引用本身可以是简单的指针(即只是一个与本机指针相同的虚拟地址,具有适合体系结构的大小),但也不必如此。一些 JVM 有非常聪明的方法来处理引用——例如,Hotspot能够在许多情况下使用 32 位值作为引用,即使在 x64 进程中运行时也是如此

于 2013-01-10T12:22:34.760 回答
2

理论上它是 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
于 2013-01-10T12:47:28.393 回答
1

没有指定确切的表示,但我认为它0x0就像在其他类似 C 的语言上一样。它是一个特殊值,否则不会出现,而不是附加字段或额外信息。

注意:当你有它时,String它是一个引用而不是一个对象。这个 4 字节的值可以引用一个对象,或者在 的情况下null是一个不是有效对象的值。

顺便说一句:大多数 64 位 JVM 使用 32 位引用,除非堆为 32 GB 或更多。这在 OpenJDK JVM 中是可能的,因为所有对象都是 8 字节(或 16 字节)对齐的。由于低 3 位或 4 位始终为 0,因此不需要将地址范围扩展为典型 4 GB 范围的 8 倍或 16 倍。

于 2013-01-10T12:22:08.643 回答
1

不应为 null 本身分配内存,因为 null 实际上不是有效的对象实例。它只是一个占位符,指示对象引用当前未引用对象。

当您执行以下操作时:

字符串 str = null;

唯一分配的是对字符串的引用(这类似于包含指针类型的语言中的字符串指针)。此引用是一个 32 位或 64 位变量(取决于您的硬件架构和 Java 版本),它驻留在堆栈中(可能取决于放置声明的确切上下文)。

于 2013-01-10T12:24:18.640 回答