有没有人试图将Java对象移出堆?我尝试通过使用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的整数,将其转换为无符号长整数,再加上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的工作方式。

关于java - 将对象移出堆,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25257400/

10-12 03:52
查看更多