本文由 ImportNew - fzr 翻译自 Peter Lawrey。欢迎加入翻译小组。转载请见文末要求。html
sun.misc.Unsafe至少从2004年Java1.4开始就存在于Java中了。在Java9中,为了提升JVM的可维护性,Unsafe和许多其余的东西一块儿都被做为内部使用类隐藏起来了。可是到底是什么取代Unsafe不得而知,我的推测会有不止同样来取代它,那么问题来了,到底为何要使用Unsafe?java
不少低级语言中可用的技巧在Java中都是不被容许的。对大多数开发者而言这是件好事,既能够拯救你,也能够拯救你的同事们。一样也使得导入开源代码更容易了,由于你能掌握它们能够形成的最大的灾难上限。或者至少明确你能够不当心失误的界限。若是你尝试地足够努力,你也能形成损害。算法
那你可能会奇怪,为何还要去尝试呢?当创建库时,Unsafe中不少(但不是全部)方法都颇有用,且有些状况下,除了使用JNI,没有其余方法作一样的事情,即便它可能会更加危险同时也会失去Java的“一次编译,永久运行”的跨平台特性。缓存
当使用框架反序列化或者构建对象时,会假设从已存在的对象中重建,你指望使用反射来调用类的设置函数,或者更准确一点是能直接设置内部字段甚至是final字段的函数。问题是你想建立一个对象的实例,但你实际上又不须要构造函数,由于它可能会使问题更加困难并且会有反作用。安全
1app 2框架 3dom 4ide 5函数 6 7 8 9 10 11 |
|
在这个类中,应该可以重建和设置final字段,但若是你不得不调用构造函数时,它就可能作一些和反序列化无关的事情。有了这些缘由,不少库使用Unsafe建立实例而不是调用构造函数。
1 2 3 |
|
调用allocateInstance函数避免了在咱们不须要构造函数的时候却调用它。
Unsafe的另一个用途是线程安全的获取非堆内存。ByteBuffer函数也能使你安全的获取非堆内存或是DirectMemory,但它不会提供任何线程安全的操做。你在进程间共享数据时使用Unsafe尤为有用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
|
当你分别在两个程序,一个输入odd一个输入even,中运行时,能够看到两个进程都是经过持久化共享内存交换数据的。
在每一个程序中,将相同的磁盘缓存映射到进程中。内存中实际上只有一份文件的副本存在。这意味着内存能够共享,前提是你使用线程安全的操做,好比volatile变量和CAS操做。(译注:CAS Compare and Swap 无锁算法)
在两个进程之间有83ns的往返时间。当考虑到System V IPC(进程间通讯)大约须要2500ns,并且用IPC volatile替代persisted内存,算是至关快的了。
我的不建议直接使用Unsafe。它远比原生的Java开发所须要的测试多。基于这个缘由建议仍是使用通过测试的库。若是你只是想本身用Unsafe,建议你最好在一个独立的类库中进行全面的测试。这限制了Unsafe在你的应用程序中的使用方式,但会给你一个更安全的Unsafe。
Unsafe在Java中是颇有趣的一个存在,你能够一我的在家里随便玩玩。它也有一些工做的应用程序特别是在写底层库的时候,但总的来讲,使用通过测试的Unsafe库比直接用要好。
原文连接: Peter Lawrey 翻译: ImportNew.com - fzr
译文连接: http://www.importnew.com/14511.html
[ 转载请保留原文出处、译者和译文连接。]