Java的随机数实现有很多坑,记录一下这次使用jdk1.8里新增的加强版随机数实现SecureRandom.getInstanceStrong() 遇到的问题。

之前在维护ali-tomcat的时候曾发现过jvm随机数算法选用不当导致tomcat的SessionID生成非常慢的情况,可以参考JVM上的随机数与熵池策略 和 Docker中apache-tomcat启动慢的问题 这两篇文章。不过当时没有太追究,以为使用了-Djava.security.egd=file:/dev/./urandom就可以避免了,在这次项目里再次遇到随机数导致所有线程阻塞之后发现这块还挺多规则。

本次项目中使用的是jdk1.8,启动参数里设置了

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

使用的随机数方式是Java8新增的:

SecureRandom.getInstanceStrong();

碰到故障时,线程阻塞在

"DubboServerHandler-xxx:20880-thread-1789" #28440 daemon prio=5 os_prio=0 tid=0x0000000008ffd000 nid=0x5712 runnable [0x000000004cbd7000]
java.lang.Thread.State: RUNNABLEat java.io.FileInputStream.readBytes(Native Method)at java.io.FileInputStream.read(FileInputStream.java:246)at sun.security.provider.NativePRNG$RandomIO.readFully(NativePRNG.java:410)at sun.security.provider.NativePRNG$RandomIO.implGenerateSeed(NativePRNG.java:427)- locked <0x00000000c03a3c90> (a java.lang.Object)at sun.security.provider.NativePRNG$RandomIO.access$500(NativePRNG.java:329)at sun.security.provider.NativePRNG$Blocking.engineGenerateSeed(NativePRNG.java:272)at java.security.SecureRandom.generateSeed(SecureRandom.java:522)

因为这个地方有加锁,locked <0x00000000c03a3c90>,所以其它线程调用到这里时会等待这个lock:

"DubboServerHandler-xxx:20880-thread-1790" #28441 daemon prio=5 os_prio=0 tid=0x0000000008fff000 nid=0x5713 waiting for monitor entry [0x000000004ccd8000]
java.lang.Thread.State: BLOCKED (on object monitor)at sun.security.provider.NativePRNG$RandomIO.implGenerateSeed(NativePRNG.java:424)- waiting to lock <0x00000000c03a3c90> (a java.lang.Object)at sun.security.provider.NativePRNG$RandomIO.access$500(NativePRNG.java:329)at sun.security.provider.NativePRNG$Blocking.engineGenerateSeed(NativePRNG.java:272)at java.security.SecureRandom.generateSeed(SecureRandom.java:522)

去查 NativePRNG$Blocking的代码,看到它的文档描述:

A NativePRNG-like class that uses /dev/random for both seed and random material. Note that it does not respect the egd properties, since we have no way of knowing what those qualities are.

奇怪怎么-Djava.security.egd=file:/dev/./urandom参数没起作用,仍使用/dev/random作为随机数的熵池,时间久或调用频繁的话熵池很容易不够用而导致阻塞;于是看了一下SecureRandom.getInstanceStrong()的文档:

Returns a SecureRandom object that was selected by using the algorithms/providers specified in the securerandom.strongAlgorithms Security property.

原来有自己的算法,在 jre/lib/security/java.security 文件里,默认定义为:

securerandom.strongAlgorithms=NativePRNGBlocking:SUN

如果修改算法值为NativePRNGNonBlocking:SUN的话,会采用NativePRNG$NonBlocking里的逻辑,用/dev/urandom作为熵池,不会遇到阻塞问题。但这个文件是jdk系统文件,修改它或重新指定一个路径都有些麻烦,最好能通过系统环境变量来设置,可这个变量不像securerandom.source属性可以通过系统环境变量-Djava.security.egd=xxx来配置,找半天就是没有对应的系统环境变量。只好修改代码,不采用SecureRandom.getInstanceStrong这个新方法,改成了SecureRandom.getInstance("NativePRNGNonBlocking")

对于SecureRandom的两种算法实现:SHA1PRNG 和 NativePRNG 跟 securerandom.source 变量的关系,找到一篇解释的很清楚的文章:Using the SecureRandom Class

On Linux:1) when this value is “file:/dev/urandom” then the NativePRNG algorithm is registered by the Sun crypto provider as the default implementation; the NativePRNG algorithm then reads from /dev/urandom for nextBytes but /dev/random for generateSeed2) when this value is “file:/dev/random” then the NativePRNG algorithm is not registered by the Sun crypto provider, but the SHA1PRNG system uses a NativeSeedGenerator which reads from /dev/random.3) when this value is anything else then the SHA1PRNG is used with a URLSeedGenerator that reads from that source.4) when the value is undefined, then SHA1PRNG is used with ThreadedSeedGenerator5) when the code explicitly asks for “SHA1PRNG” and the value is either “file:/dev/urandom” or “file:/dev/random” then (2) also occurs6) when the code explicitly asks for “SHA1PRNG” and the value is some other “file:” url, then (3) occurs7) when the code explicitly asks for “SHA1PRNG” and the value is undefined then (4) occurs

至于SHA1PRNG算法里,为何用urandom时,不能直接设置为file:/dev/urandom而要用变通的方式设置为file:///dev/urandom或者 file:/dev/./urandom,参考这里:

In SHA1PRNG, there is a SeedGenerator which does various things depending on the configuration.

  1. If java.security.egd or securerandom.source point to “file:/dev/random” or “file:/dev/urandom”, we will use NativeSeedGenerator, which calls super() which calls SeedGenerator.URLSeedGenerator(/dev/random). (A nested class within SeedGenerator.) The only things that changed in this bug was that urandom will also trigger use of this code path.

  2. If those properties point to another URL that exists, we’ll initialize SeedGenerator.URLSeedGenerator(url). This is why “file:///dev/urandom”, “file:/./dev/random”, etc. will work.

参考:The Right Way to Use SecureRandom

SecureRandom生成随机数慢(阻塞)问题解决记录相关推荐

  1. 利用计算机可产生随机数,一种利用计算机生成随机数的方法

    一种利用计算机生成随机数的方法 (2012-07-16 23:22:33) 标签: 随机数 函数 数值 计数器 程序运行 杂谈 这里介绍一种利用计算机生成随机数的方法,微机都有系统计数器记录自运行开始 ...

  2. Java生成随机数的4种方式,以后就用它了!

    作者 | 王磊 来源 | Java中文社群(ID:javacn666) 转载请联系授权(微信ID:GG_Stone) 在 Java 中,生成随机数的场景有很多,所以本文我们就来盘点一下 4 种生成随机 ...

  3. mysql语句随机数_程序生成随机数与SQL语句生成随机数

    随机数可以通过程序生成,也可以通过SQL语句生成.通过程序生成随机数时一般采用硬件的编号+时间作为种子,这种方法在瞬间插入数据库N条数据的时候会影响随机数的效果,生成很多相邻的插入值相同.所以频繁插入 ...

  4. java 生成随机数_Java 生成随机数的 N 种方法

    原标题:Java 生成随机数的 N 种方法 www.baeldung.com/java-generating-random-numbers 1.引言 本文将探讨用 Java 生成随机数的不同方法. 2 ...

  5. Java 生成随机数的 N 种方法

    (给ImportNew加星标,提高Java技能) 编译:ImportNew/覃佑桦 www.baeldung.com/java-generating-random-numbers 1.引言 本文将探讨 ...

  6. linux 生成随机数 命令,Linux生成随机数的多种方法

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 通过内部系统变量 $RANDOM 如果超过 5 位可以加个固定 10 位整数,然后进行求余.生成 400000~5000 ...

  7. securerandom java_Java 随机数 Random VS SecureRandom

    更多 Java 基础知识方面的文章,请参见文集<Java 基础知识> 1. Math.random() 静态方法 产生的随机数是 0 - 1 之间的一个 double,即 0 <= ...

  8. 在多个指定区间内生成随机数,且随机数总和固定算法

    在多个指定区间内生成随机数,且随机数总和固定算法 一.介绍 最近项目上遇到了一个需求就是在多个指定区间内生成总和恒定的随机数. 示例:在[1-3].[4-20].[24-100]区间上分别生成一个随机 ...

  9. java 生成随机数_不会生成随机数?我们来看看java生成随机数的10种方法

    1.引言 本文将探讨用 Java 生成随机数的不同方法. 2.Java API Java API 提供了几种随机数生成方法.让我们一起来了解一下. 2.1.java.lang.Math Math 类中 ...

  10. Java生成随机数的方式

    目录 Random 基础使用 优缺点分析 SecureRandom 基础使用 总结: 持续更新 Random Random 类诞生于 JDK 1.0,它产生的随机数是伪随机数,也就是有规则的随机数.R ...

最新文章

  1. Ext Scheduler Web资源甘特图控件
  2. apache的日志级别和设置
  3. python爬去百度文库_利用Python语言轻松爬取数据[精品文档]
  4. CF1305D Kuroni and the Celebration
  5. 深度学习推荐模型-DIN
  6. 两个app应用之间的跳转
  7. 系统集成项目管理工程师成绩合格标准
  8. vs2010sp1安装失败问题
  9. 平面设计中的对比设计技巧
  10. FPGA控制_步进电机模块使用说明
  11. 云计算 | 浅议云计算发展趋势
  12. c语言改变图片颜色,用c语言把bmp格式的彩色图片转换成黑白的
  13. 2.12 二项式系数加法解 C实现
  14. 如何动态使用烘焙出来的ReflectionProbe-0.exr信息
  15. 海量向量搜索引擎 Milvus 开源啦
  16. 获取有道词典在线翻译结果 及 Windows下配置运行ASP
  17. awesome nostr
  18. 身份证很快将不用随身带了
  19. 【SAS】format和informat
  20. C语言:指出程序中的问题总结(一)

热门文章

  1. mysql .net2.0_MySQL和.Net2.0合营哄骗
  2. maven profiles配置_nexus3搭建maven私服(完整版)
  3. oninput、onchange、onpropertychange的区别
  4. css中的伪类与伪元素的区别
  5. Linux命令整理-Kali
  6. Python学习之面向对象(一)
  7. hdu--1160--LIS+打印路径
  8. java通过jdbc访问数据库
  9. Java命名规范+常量定义方法
  10. MongoDB安装、配置与示例