这段(不安全的)代码可能会导致JVM崩溃吗?

3
稍微修改自这里的内容:
import sun.misc.Unsafe;
import java.lang.reflect.*;

public class K {
    private static Unsafe unsafe;
    private static int fieldOffset;
    private static K instance = new K();

    static {
        try {
            Field f = Unsafe.class.getDeclaredField("theUnsafe");
            f.setAccessible(true);

            unsafe = (Unsafe) f.get(null);

            fieldOffset = unsafe.fieldOffset(K.class.getDeclaredField("obj"));
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    private Object obj;

    public synchronized static long toAddress(int o) {
        instance.obj = o;
        return unsafe.getLong(instance, fieldOffset);
    }

    public synchronized static Object toObject(long address) {
        unsafe.putLong(instance, fieldOffset, address);
        return instance.obj;
    }

    public static void main(String[] args) {
        int x = 20;

        System.err.println("x was = " + x);
        long addr = toAddress(x);
        System.err.println("&x = " + addr);
        x = 70;
        System.out.println("x is now " + x);
        long newAddr = toAddress(x);
        System.err.println("new (&x) = " + newAddr);

        System.out.println("Previous value of x is " + toObject(addr)); // !!!
    }
}

特别是,我担心标有!!!的那行。如果原始的x被垃圾回收了,那么它的地址可能就毫无价值了。

我的问题是,JVM会崩溃吗?还是toObject(BOGUS_VALUE)总是会失败并抛出一个NullPointerException(可以捕获)?

正如大多数人所知道的,Unsafe文档的质量最好也只能算得上参差不齐。


不会的。它会在早期抛出NullPointerException,即在“unsafe =(Unsafe)f.get(null);”处。 - Elliott Frisch
@ElliottFrisch,不,它不会。我认为这是一种正常且经典的获取类的静态字段的方式。如果theUnsafe是实例变量,你说得对。 - tkroman
抱歉,我再看了一遍。我以为 OP 在 K 中访问的是 unsafe,而不是这里的字段 Unsafe - Elliott Frisch
在这种情况下,由Autoboxing创建的整数对象不会被垃圾回收,因为Integer在静态数组中保持对它的引用。 - user253751
1个回答

3

我添加了一些代码,在尝试检索丢失的对象之前可能会导致垃圾回收。

for (int i = 0; i < 1000000; i ++) {
    new Object().toString();
}
System.out.println("Previous value of x is " + toObject(addr).getClass()); // !!!

并且获得了一个。
#  SIGSEGV (0xb) at pc=0x000000010e627c46, pid=49698, tid=6403

您所访问的地址可能不再指向可被视为对象的内容,它是不安全的(Unsafe)。

我尝试做了类似的事情,但我的垃圾回收器没有启动。看起来你比我(不)幸运:) 谢谢! - David Titarenco

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接