David Titarenco
David Titarenco

Reputation: 33406

Could this (unsafe) code crash the JVM?

Slightly modified from here:

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)); // !!!
    }
}

In particular, I'm worried about the line marked with !!!. If the original x gets garbage collected then its address will presumably be worthless.

My question is will the JVM segfault or will toObject(BOGUS_VALUE) always fail with a NullPointerException (which can be caught)?

As I'm sure most of you know, the Unsafe documentaton is spotty at best.

Upvotes: 3

Views: 708

Answers (1)

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 280102

I added some code that would potentially cause a GC before trying to retrieve the lost object.

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

and got a

#  SIGSEGV (0xb) at pc=0x000000010e627c46, pid=49698, tid=6403

The address you have probably no longer points to something that could be considered an object. It is Unsafe.

Upvotes: 3

Related Questions