先记录一下两个帖子的地址:
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一下。(这点是自己总结的)