本文由 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
[ 轉載請保留原文出處、譯者和譯文連接。]