先記錄一下兩個帖子的地址:
1. Proper Use Of Java SecureRandom
2. The Right Way to Use SecureRandom
JDK版本: 1.8.0_66
事情的起因還是 SecureRandom.generateSeed()在Linux系統上卡住導致線程block這個現象。見討論:
http://stackoverflow.com/questions/137212/how-to-solve-performance-problem-with-java-securerandom
事實上,如果使用SecureRandom.getInstanceStrong()這種方法初始化SecureRandom對象的話,也會在Linux上產生類似問題。
記錄一下知識點(這玩意兒其實挺冷門的):
1.SecureRandom本身並不是偽隨機算法的實現,而是使用了其他類提供的算法來獲取偽隨機數。
2.如果簡單的new一個SecureRandom對象的話,在不同的操作平台會獲取到不同的算法,windows默認是SHA1PRNG,Linux的話是NativePRNG。
3. Linux下的NativePRNG,如果調用generateSeed()方法,這個方法會讀取Linux系統的/dev/random文件,這個文件在JAVA_HOME/jre/lib/securiy/java.security里面有默認定義。而/dev/random文件是動態生成的,如果沒有數據,就會阻塞(后面這句結論阻塞正確,至於為什么阻塞沒細看)。也就造成了第一個現象。
4.可以使用-Djava.security.egd=file:/dev/./urandom (這個文件名多個u)強制使用/dev/urandom這個文件,避免阻塞現象。中間加個點的解釋是因為某個JDK BUG,SO那個帖子有鏈接。
5.如果使用SecureRandom.getInstanceStrong()這種方法初始化SecureRandom對象的話,會使用NativePRNGBlocking這個算法,而NativePRNGBlocking算法的特性如下:
NativePRNGBlocking uses /dev/random for all of the following operations:
Initial seeding: This initializes an internal SHA1PRNG instance using 20 bytes from /dev/random
Calls to nextBytes(), nextInt(), etc.: This provides the XOR of the output from the internal SHA1PRNG instance (see above) and data read from /dev/random
Calls to getSeed(): This provides data read from /dev/random
可見這個算法完全依賴/dev/random,所以當這個文件隨機數不夠的時候,自然會導致卡頓了。
6.如果使用NativePRNGBlocking算法的話,4中的系統參數失效!!!(這個是從http://hongjiang.info/java8-nativeprng-blocking/看到的)
7.一般使用SecureRandom不需要設置Seed,不需要設置算法,使用默認的,甚至一個靜態的即可,如果有需求的話可以在運行一段時間后setSeed一下。(這點是自己總結的)