将对象移离堆

时间:2014-08-12 06:17:31

标签: java unsafe

有没有人试图将Java对象移出堆?我尝试使用不安全的库来使用序列化,反序列化和存储字节数组。但是复杂的对象中包含多个对象,这使得这个过程非常繁琐。更好的解决方案?

2 个答案:

答案 0 :(得分:15)

不安全字段是您的不安全实例。如果您不知道如何获得它,只需使用:

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;
}

您可以使用以下方式分配offheap空间:

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);

然后,锚应该是你的对象从offheap!

注意:完成后,请记住释放已分配内存的资源:

unsafe.freeMemory(address);

(见,告诉你地址很重要[好像已经不是很明显了])

来源:http://highlyscalable.wordpress.com/2012/02/02/direct-memory-access-in-java/,一个名叫RawCode的好人,我不相信这里,但是告诉我一段时间之前不安全的情况。

答案 1 :(得分:1)

有些库使这个过程至少不那么大惊小怪,最多存储和更多对象更有效地进出堆内存。首先想到Chronicle ValuesSlab,但我记得还有更多。