偶遇 JDK 1.8 还未修复的 SecureRandom.getInstance(“SHA1PRNG”) 之 bug

楼主今天兴高采烈的在部署环境,下载 JDK,打包项目,上传至服务器。

配置 JDK ,打包上传项目楼主就不在这里重复了,读者自行解决哈!

1. 启动项目

java -jar xxxx.jar 

令楼主没有想到的是:程序卡主了,卡在了数据库建立连接的位置。(查看方法方式: jstack <pid> 即可)

2. 堆栈信息

由于是项目刚一启动,初始化数据库连接池,并没有太多的线程堆栈。这里我贴一下我遇到的主要问题的堆栈信息:

或许你会问我,为什么你要定位到这个线程?主要是因为道友经过好几次 jstack 操作,发现该线程一直都停留在该位置,这就足以说明这个线程是当前线程!

3. 分析堆栈信息

从上面的堆栈信息中,我们可以得知那些信息?

  • 当前线程名称为 : restartedMain
  • 当前线程状态为: RUNNABLE
  • 当前线程 ID: 0x00007f4430002800
  • native 线程 ID: 0x65b0
  • 当前运行位置 : at java.io.FileInputStream.readBytes(Native Method)

通过分析堆栈,想必读取文件不会有什么问题,我们往线程堆栈的上层追踪。目标点落在 

    at sun.security.provider.SeedGenerator$URLSeedGenerator.getSeedBytes(SeedGenerator.java:539)

很明显,这里是  JDK 源码的调用,接下来打卡 jdk 源码进行查看!

4. 源码分析

我们通过堆栈信息一步步跟进源码查看,

从方法  nextBytes 上来看,他调用这个是为了:生成用户指定的随机字节数。好吧,那就是它在生成的时候,需要读取某个文件来生成随机数。

5. 写个测试验证想法

紧接着执行

javac HelloWorld.java

这个要是读者你不会,那你就放弃java吧,java 界可能不适合你。

接下来执行 

java HelloWorld

执行后,,的结果是 

[ryan@ryanmacbook ~]

$

卡住了,楼主强制 kill 了。

说明我们的问题点就是这里。

接下来,解决办法是啥?你要问楼主楼主也不知道,咋办?上百度呗,百度都不会用的程序员不是好程序员:

6. 解决办法

最后的解决办法就是 ,在项目启动的时候,修改 java.security.egd,通过如下方式,专业术语叫做    熵池策略   

java -Djava.security.egd=file:/dev/urandom HelloWorld

问题的本质还是 Oracle 驱动类中调用了 SecureRandom.nextBytes() 。楼主还没来得及看其他驱动程序是否也有这个问题,当然也不排除与操作系统有关系。待验证其他操作系统后,再补充!

果断成功!

道友查了下,说是 JVM 的 bug , 在收集噪点的时候没有收集全导致的。如果你的也有遇到这样的问题,时而可用,时而不可用,那就是噪点收集的问题。

[参考链接] http://ifeve.com/jvm-random-and-entropy-source/

2 thoughts on “偶遇 JDK 1.8 还未修复的 SecureRandom.getInstance(“SHA1PRNG”) 之 bug

Leave a Comment

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据