环境
CentOS 7.3
JRE 1.8
Lagom, Play, Scala, Java
问题
有个功能运行时特别慢,后来逐句跟踪发现是new SecureRandom().engineGenerateSeed(16)
特别慢(用于产生随机数的)。
解决
用-Djava.security.egd=file:/dev/./urandom
指定随机种子文件(熵池);
或修改JVM配置文件$JAVA_PATH/jre/lib/security/java.security,改为:
securerandom.source=file:/dev/./urandom
解惑
SecureRandom默认使用/dev/random种子文件,但/dev/random是一个阻塞的数字生成器,依赖于设备的活动来刷新随机数据,如果没有活动就等待,进而导致JVM等待。这在服务器端尤其容易发生(因为设备活动少)。
SecureRandom的代码实现也有个缺陷:如果种子文件指定的是
file:/dev/random
或file:/dev/urandom
,那么JVM会使用本地种子产生器NativeSeedGenerator,它会调用super()方法,即调用SeedGenerator.URLSeedGenerator(/dev/random)
方法进行初始化。只有指定其他文件才会用SeedGenerator.URLSeedGenerator(url)
方法进行初始化。/dev/urandom文件是dev/random的一个副本,但它是非阻塞的随机数发生器,会重复使用熵池中的数据以产生伪随机数据。因而它输出的熵可能小于/dev/random,不建议用于生成高强度长期密码。