将对象移离堆
有没有人试图将Java对象移出堆? 我尝试使用不安全的库来使用序列化,反序列化和存储字节数组。 但是复杂的对象中有多个对象,这使得这个过程非常繁琐。 更好的解决方案?
不安全字段是您的不安全实例。 如果您不知道如何获得它,只需使用:
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的好人我不相信在这里,但告诉我一段时间以前的不安全工作方式。
有些库使这个过程至少不那么大惊小怪,最多存储和更多对象更有效地进出堆内存。 我首先想到了Chronicle Values和Slab ,但我记得还有更多。