jdk java.security.SecureRandom 性能问题

SecureRandom在java各种组件中使用广泛,可以可靠的产生随机数。但在大量产生随机数的场景下,性能会较低。这时可以使用"-Djava.security.egd=file:/dev/./urandom"加快随机数产生过程。

以产生uuid的时候使用nextBytes产生随机数为入口,我们看一下SecureRandom的代码逻辑。

 public static UUID randomUUID() {
        SecureRandom ng =Holder.numberGenerator;

        byte[] randomBytes = newbyte[16];
        ng.nextBytes(randomBytes);
        randomBytes[6] &= 0x0f;  /* clear version       */
        randomBytes[6]  |=0x40;  /* set to version 4     */
        randomBytes[8] &= 0x3f;  /* clear variant       */
        randomBytes[8]  |=0x80;  /* set to IETF variant  */
        return newUUID(randomBytes);
    }

使用了SecureRandom.next*的方法。

在使用SecureRandom产生下一个随机数的时候调用nextLong或者nextBytes,最终会调用SecureRandom的nextBytes。

public long nextLong() {
        // it‘s okay that the bottom wordremains signed.
        return ((long)(next(32)) << 32)+ next(32);
    } 

    final protected int next(int numBits) {
        int numBytes = (numBits+7)/8;
        byte b[] = new byte[numBytes];
        int next = 0; 

        nextBytes(b);
        for (int i = 0; i < numBytes; i++)
            next = (next << 8)+ (b[i] & 0xFF);
        return next >>> (numBytes*8 -numBits);
    }

而nextBytes是一个同步的方法,在多线程使用时,可能会产生性能瓶颈。

synchronized public void nextBytes(byte[] bytes) {
       secureRandomSpi.engineNextBytes(bytes);
    }

secureRandomSpi被初始化为sun.security.provider.SecureRandom

secureRandomSpi是SecureRandom.NativePRNG的一个实例。

使用jvm参数-Djava.security.debug=all ,可以打印securityprovider列表,从中可以看出,SecureRandom.NativePRNG由sun.security.provider.NativePRNG提供服务。

Provider: Set SUN provider property[SecureRandom.NativePRNG/sun.security.provider.NativePRNG]

分析openjdk的源码,NativePRNG.engineNextBytes调用了NativePRNG.RandomIO.ensureBufferValid,而ensureBufferValid直接从urandom读取数据:

private void ensureBufferValid() throws IOException {
            ...
            readFully(urandomIn, urandomBuffer);
            ...
        }

通过测试可以发现,hotspot需要使用配置项"-Djava.security.egd=file:/dev/./urandom"才能从urandom读取数据,这里openjdk做了优化,直接从urandom读取数据。

/dev/random在产生大量随机数的时候比/dev/urandom慢,所以,建议在大量使用随机数的时候,将随机数发生器指定为/dev/./urandom。

注意:jvm参数值为/dev/./urandom而不是/dev/urandom,这里是jdk的一个bug引起。

bug产生的原因请注意下面第四行源码,如果java.security.egd参数指定的是file:/dev/random或者file:/dev/urandom,则调用了无参的NativeSeedGenerator构造函数,而无参的构造函数将默认使用file:/dev/random 。openjdk的代码和hotspot的代码已经不同,openjdk在后续产生随机数的时候没有使用这个变量。

abstract class SeedGenerator {
......
    static {
        String egdSource = SunEntries.getSeedSource();
        if (egdSource.equals(URL_DEV_RANDOM) || egdSource.equals(URL_DEV_URANDOM)) {
            try {
                instance = new NativeSeedGenerator();
                if (debug != null) {
                    debug.println("Using operating system seed generator");
                }
            } catch (IOException e) {
                if (debug != null) {
                    debug.println("Failed to use operating system seed "
                                  + "generator: " + e.toString());
                }
            }
        } else if (egdSource.length() != 0) {
            try {
                instance = new URLSeedGenerator(egdSource);
                if (debug != null) {
                    debug.println("Using URL seed generator reading from "
                                  + egdSource);
                }
            } catch (IOException e) {
                if (debug != null)
                    debug.println("Failed to create seed generator with "
                                  + egdSource + ": " + e.toString());
            }
        }
......
    }

http://www.usn-it.de/index.php/2009/02/20/oracle-11g-jdbc-driver-hangs-blocked-by-devrandom-entropy-pool-empty/



https://blog.51cto.com/leo01/1795447

原文地址:https://www.cnblogs.com/dflvlj/p/10824295.html

时间: 2024-11-05 11:57:36

jdk java.security.SecureRandom 性能问题的相关文章

java.security.SecureRandom源码分析 java.security.egd=file:/dev/./urandom

SecureRandom在java各种组件中使用广泛,可以可靠的产生随机数.但在大量产生随机数的场景下,性能会较低. 这时可以使用"-Djava.security.egd=file:/dev/./urandom" 加快随机数产生过程. http://blog.51cto.com/leo01/1795447 原文地址:https://www.cnblogs.com/antball/p/9667234.html

java uuid和SecureRandom性能详解

1. java.security.SecureRandom源码分析 jdk产生uuid的代码: public static UUID randomUUID() { SecureRandom ng =Holder.numberGenerator; byte[] randomBytes = newbyte[16]; ng.nextBytes(randomBytes); randomBytes[6] &= 0x0f;  /* clear version       */ randomBytes[6] 

java.security.NoSuchAlgorithmException: SHA1PRNG SecureRandom not available

q好久没有使用MyEclipse10了,今天打开看了以前大学的项目,在Tomcat7中发布启动,我嚓嘞,报错: SEVERE: Exception initializing random number generator using algorithm [SHA1PRNG] java.security.NoSuchAlgorithmException: SHA1PRNG SecureRandom not available at sun.security.jca.GetInstance.getI

Java Security:Java加密框架(JCA)简要说明

加密服务总是关联到一个特定的算法或类型,它既提供了密码操作(如Digital Signature或MessageDigest),生成或供应所需的加密材料(Key或Parameters)加密操作,也会以一个安全的方式生成数据对象(KeyStore或Certificate),封装(压缩)密钥(可以用于加密操作). Java Security API中,一个engine class就是定义了一种加密服务,不同的engine class提供不同的服务.下面就来看看有哪些engine class: 1)M

andorid HTTPS 不需要证书 VolleyEror: com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not fou

1.加证书(这里不说) 2.修改代码 import java.security.KeyManagementException;import java.security.NoSuchAlgorithmException;import java.security.SecureRandom;import java.security.cert.X509Certificate;import javax.net.ssl.HostnameVerifier;import javax.net.ssl.HttpsU

深入理解Android之Java Security第一部分

深入理解Android之Java Security(第一部分) 从事Android工作4年以来,只有前1年不到的时间是用C++在开发东西(主要是开发DLNA组件,目前我已将它们全部开源,参考http://blog.csdn.net/innost/article/details/40216763),后面的工作几乎都在用Java.自以为Java相关的东西都见过了,可前段时间有个朋友给我花了1个多小时讲解他们某套系统的安全体系结构,其中涉及到很多专业术语,比如Message Digest(消息摘要).

Java学习-050-AES256 之 java.security.InvalidKeyException: Illegal key size or default parameters 解决方法

在进行 Java AES 加密测试时,出现如下错误信息: java.security.InvalidKeyException: Illegal key size or default parameters at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1026) at javax.crypto.Cipher.implInit(Cipher.java:801) at javax.crypto.Cipher.chooseProvider(Cip

Java Se:Java Security

Java API中有很多都使用了SecurityManager,这到底是什么玩意?最近看公司的产品的源码,也有不少SecurityManager.AccessControlContext等相关的代码,只是知道它们与安全有关,但是它们到底是怎么一回事呢?Spring也有一个Security框架,与Java Security有什么关联呢?另外有经验的开发人员调试程序时可能会查看ProtectionDomain.CodeSource,这两者又是什么呢? Java Sandbox 提到Java Secu

How to improve Java&amp;#39;s I/O performance( 提升 java i/o 性能)

原文:http://www.javaworld.com/article/2077523/build-ci-sdlc/java-tip-26--how-to-improve-java-s-i-o-performance.html JDK 1.0.2 的 java.io 包暴露了非常多I/O性能问题.这里将介绍一个优化方案,附加一个关闭同步的方法. Java的I/O性能以前是非常多Java应用的瓶颈.主要原因就是JDK1.0.2的java.io包的不良设计和实现.关键问题是缓冲.绝大多数java.i