sun.misc.Unsafe和堆外内存

sun.misc.Unsafe类允许您执行许多Java中不应该做的事情,但是在非常特殊的情况下仍然有用。 必须在99%的时间避免这种情况,但是在极少数情况下,这是唯一有意义的解决方案。

这篇文章考虑了它在OpenHFT中的使用方式以及我希望在Java 9中看到的功能。特别地,可以通过这种方式完成访问大量内存而不影响GC的工作。 只有在Java中才能通过这种方式在进程之间共享内存,而不会产生大量开销。

分配和释放堆内存。

public native long allocateMemory();
public native void freeMemory(long address);

这两种方法允许您分配任何大小的堆外内存。 它不限于Integer.MAX_VALUE字节,您会获得原始内存,可以在其中应用边界检查。 例如,Bytes.writeUTF(String)计算编码字符串的长度,并检查整个字符串是否适合一次(而不是每个字节)。

Java-Lang使用与DirectByteBuffer用来确保释放内存相同的内部Cleaner类。 理想情况下,这不会那么内部。

原始访问内存

public native Xxx getXxx(Object, long offset); // intrinsic
public native void putXxx(Object, long offset);// intrinsic

在这两种情况下,处理堆外内存时,Object均为null,并且偏移量只是地址。 这使您可以使用针对JVM的单个机器代码指令来执行RAW内存访问,这些指令会威胁到它们作为内在函数。 这显着提高了内存访问的性能。

这种原始方法的问题在于,您必须自己管理数据结构中字段的布局。 Java-Lang库通过允许您定义getter和setter的接口(甚至对于String和enums等对象类型)来解决此问题,它将在运行时生成实现。 即,您可以访问getter / setter,而无需知道“对象”已脱离堆。

线程安全访问内存

public native Xxx getVolatileXxx(Object, long offset); // intrinsic
public native void putOrderedXxx(Object, long offset); // intrinsic

这两种方法使您可以将惰性字段与惰性集一起使用。 对于设置线程,惰性设置速度更快,但是如果设置得太快,则可能导致同一线程读取旧值。 解决方案是不要读取您刚刚编写的值。

当在进程之间共享数据时,这些方法特别有用。

CAS操作

public native boolean compareAndSwapXxxx(Object, long offset, Xxx expected, Xxx setTo) // intrinsic

此方法对于构建锁定堆至关重要。 特别是在进程之间以线程安全的方式共享数据的最有效方法。 在我对Haswell i7-4500处理器进行的测试中,同一台计算机上两个进程的往返延迟通常是这样。

TCP协议 – 9微秒。
文件锁 – 5.5微秒。
中国科学院 – 0.12微秒。
有序写 – 0.02微秒(半往返,如果可以使用此模式)

堆对象分配

public native Object allocateInstance(Class clazz);

在反序列化一个类时,您希望按照序列化时的方式重新构造该类中的值。 如JEP 187:序列化2.0所述,这不适用于当前的构造函数,一种解决方法是完全避免构造函数,并创建实例而不调用实例。 这在很大程度上取决于信任您拥有的数据,但是它具有易于使用的优点,并且不假设您拥有哪些构造函数。

结论

经常注意到,在没有网络开销的情况下,嵌入式数据库可以在延迟方面胜过分布式数据库。 我相信下一代低延迟数据库将提供嵌入式性能并在进程之间共享,并且更新和查询响应时间都将大大低于一微秒。

我认为没有理由不应该在Java中实现这些功能。 对于Java用户,本机接口性能最佳,因为它不需要JNI或将世界的C视图转换为Java视图。

参考: sun.misc。来自Vanilla Java博客的JCG合作伙伴 Peter Lawrey提供的不安全和堆外内存

翻译自: https://www.javacodegeeks.com/2014/01/sun-misc-unsafe-and-off-heap-memory.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值