Reputation: 33406
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
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