unsafe 字段是您的 Unsafe 实例。如果您不知道如何获取它,只需使用:
Unsafe unsafe = getUnsafe();
Unsafe getUnsafe() {
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
return (Unsafe) f.get(null);
} catch (Exception x) {
x.printStackTrace();
}
return null;
}
请记住,这应该适用于 HotSpot JVM,因为字段名称在不同的实现中有所不同。
您可以通过以下方式将对象移出堆:
1) 为内存地址分配适当的字节。您可以在偏移量 4L 处读取 int,转换为 unsigned long,然后添加 12L,并获取该位置的地址。
一个示例实现:
public static long sizeOf(Object object) {
return unsafe.getAddress( normalize( unsafe.getInt(object, 4L) ) + 12L );
}
public static long normalize(int value) {
if(value >= 0) return value;
return (~0L >>> 32) & value;
}
您可以使用以下方法分配堆外空间:
Object object = // Your object
long size = sizeOf(object);
long address = unsafe.allocateMemory(size);
(保持地址字段方便)
2) 将对象复制到地址指定的内存段中。
例子:
getUnsafe().copyMemory(
object,
0,
null,
address,
size);
完成!现在你的对象是堆外对象。
要取回您的对象,只需执行以下操作:
// Class wide field
Object anchor;
// Deserializarion
long offset = unsafe.objectFieldOffset(this.getClass().getDeclaredField("anchor"));
unsafe.putLong(this, offset, address);
那么,anchor 应该是你的堆外对象!
注意:请记住在完成以下操作时释放已分配内存的资源:
unsafe.freeMemory(address);
(看,告诉过你地址很重要[好像还不是很明显])
来源:http://highlyscalable.wordpress.com/2012/02/02/direct-memory-access-in-java/,一位名叫 RawCode 的好人,我不相信他在这里,但不久前告诉我 Unsafe 的工作原理。