如何修改Java随机数据源 解决/dev/random阻塞引发的程序挂起问题
Java程序因/dev/random熵池不足挂起的可行解决方法
问题背景说明
机器/dev/random熵池填充速度过慢时,Java默认会调用阻塞式的/dev/random生成安全随机数,导致程序挂起。尝试过多个格式的-Djava.security.egd启动参数未生效,可通过以下方案解决:
解决方法
方案1:修改JRE全局安全配置(兼容性最强,优先推荐)
- 找到JRE安装路径下的配置文件:
$JRE_HOME/lib/security/java.security - 定位到如下配置行:
securerandom.source=file:/dev/random
- 修改为:
securerandom.source=file:/dev/./urandom
修改后所有运行在该JRE上的Java程序都会默认使用非阻塞的urandom生成随机数,无需再单独添加启动参数。
方案2:补充完整启动参数
部分旧版本Java需要同时指定两个随机数相关的启动参数才会生效,启动时添加如下参数即可:
-Djava.security.egd=file:/dev/./urandom -Dsecurerandom.source=file:/dev/./urandom
方案3:安装熵补充工具(不修改Java配置,随机数质量更高)
如果不想牺牲随机数质量,也不想修改Java相关配置,可以直接安装系统级熵生成工具加速熵池填充:
- Debian/Ubuntu系操作系统执行:
apt install haveged && systemctl enable --now haveged - CentOS/RHEL系操作系统执行:
yum install haveged && systemctl enable --now haveged
haveged服务会基于系统硬件噪声持续生成熵填充到/dev/random池,从根源解决随机数阻塞问题,随机数安全性高于直接使用urandom。
方案4:指定非阻塞的SecureRandom实现(Java 8+适用)
如果使用Java 8及以上版本,可在启动参数中额外指定强随机数的非阻塞实现:
-Dsecurerandom.strongAlgorithms=NativePRNGNonBlocking:SUN
该配置可以保证代码中显式调用SecureRandom.getInstanceStrong()时也不会触发阻塞。
配置生效验证
可以编写简单的测试代码验证配置是否生效:
import java.security.SecureRandom; public class RandomTest { public static void main(String[] args) { long start = System.currentTimeMillis(); SecureRandom random = new SecureRandom(); byte[] buffer = new byte[16]; random.nextBytes(buffer); System.out.println("随机数生成耗时:" + (System.currentTimeMillis() - start) + "ms"); } }
执行后如果耗时在100ms以内说明配置已生效,没有走阻塞的/dev/random接口。
内容的提问来源于stack exchange,提问作者Greg Dougherty
相关产品推荐
相关产品推荐

