JDK-8098581 : SecureRandom.nextBytes() hurts performance with small size requests
  • Type: Bug
  • Component: security-libs
  • Sub-Component: java.security
  • Affected Version: 8
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2015-06-15
  • Updated: 2017-05-17
  • Resolved: 2016-02-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
8u112Fixed 9 b105Fixed
Related Reports
Duplicate :  
Sub Tasks
JDK-8156684 :  
Server threads were shown to be blocked and timeout during PAE testing.  This showed up more in smaller heap sizes.  Pulling many bytes and buffering would help this.

java.lang.Thread.State: BLOCKED (on object monitor)
at java.security.SecureRandom.nextBytes(SecureRandom.java:457)
- waiting to lock <0x00000007a256cc20> (a java.security.SecureRandom)
at sun.security.util.KeyUtil.checkTlsPreMasterSecretKey(KeyUtil.java:205)
at com.sun.crypto.provider.RSACipher.engineUnwrap(RSACipher.java:459)
at javax.crypto.Cipher.unwrap(Cipher.java:2506)
at sun.security.ssl.RSAClientKeyExchange.<init>(RSAClientKeyExchange.java:120)
at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:238)

java.lang.Thread.State: RUNNABLE
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:255)
at sun.security.provider.NativePRNG$RandomIO.readFully(NativePRNG.java:410)
at sun.security.provider.NativePRNG$RandomIO.ensureBufferValid(NativePRNG.java:473)
at sun.security.provider.NativePRNG$RandomIO.implNextBytes(NativePRNG.java:487)
- locked <0x00000007a08a8ec0> (a java.lang.Object)
at sun.security.provider.NativePRNG$RandomIO.access$400(NativePRNG.java:329)
at sun.security.provider.NativePRNG.engineNextBytes(NativePRNG.java:218)
at java.security.SecureRandom.nextBytes(SecureRandom.java:457)
- locked <0x00000007a256cc20> (a java.security.SecureRandom)
at sun.security.ssl.CipherBox.createExplicitNonce(CipherBox.java:1015)
[~coffeys] Thanks for your information. I'm not sure how this entropy works. But, it seems it's not the reason for this problem. As the article suggested, I've checked the available entropy value. It's 133 which is between the suggested 100-200.

in response to Tony Wen's updates : Lack of entropy in linux can be problematic in such cases. E.g. https://major.io/2007/07/01/check-available-entropy-in-linux/

Anthony, thanks for help. I've tested the code on Linux and Mac OS. It only happens on Linux. So, most likely this is an OS level problem.

I have heard in the past that Linux was slow on generating random numbers, but I have never experienced it. Since the thread is stuck on FileInputStream.readBytes() my first guess would be the OS. Windows is using a different random number implementation, and I do not know the quality of Microsoft's random number generator. I would assume it's ok. Solaris or Mac OS I believe use the same implementation, NativePRNG. If Solaris and MacOS both were slow, then it might point to something in the NativePRNG implementation.

Anthony, thanks for your quick reply. I can understand what you side about the big buffer size. But, I found the same code works well on Windows. The difference is the algorithm implementation. On Windows, it's "securerandom.strongAlgorithms=Windows-PRNG:SunMSCAPI,SHA1PRNG:SUN", while on Linux is "securerandom.strongAlgorithms=NativePRNGNonBlocking:SUN". I'm not familiar about these algorithms. It seems they are both provided by us(Oracle/SUN). Why do they perform this different? Is there any Linux OS level reason that makes the implementation on Linux cannot performance well like the implementation on Windows? Please forgive me if I asked a silly question.

Unless I'm read the API wrong your BigInteger constructor is getting 2^130 bits of random data. The buffer is 1.3x10^39 bits big. I'm sure the thread locks because that is a very large buffer. Random numbers have to be generated, so linux could have stalled or slowed trying to generate that much.

I've tried build but still got similar performance problem on Ubuntu 14.04. Would you please help to check on this? My Java version: java version "1.8.0_122" Java(TM) SE Runtime Environment (build 1.8.0_122-b08) Java HotSpot(TM) 64-Bit Server VM (build 25.122-b08, mixed mode) Stack where our application stuck: java.lang.Thread.State: RUNNABLE at java.io.FileInputStream.readBytes(Native Method) at java.io.FileInputStream.read(FileInputStream.java:255) at sun.security.provider.NativePRNG$RandomIO.readFully(NativePRNG.java:424) at sun.security.provider.NativePRNG$RandomIO.ensureBufferValid(NativePRNG.java:525) at sun.security.provider.NativePRNG$RandomIO.implNextBytes(NativePRNG.java:544) - locked <0x00000006c037f090> (a java.lang.Object) at sun.security.provider.NativePRNG$RandomIO.access$400(NativePRNG.java:331) at sun.security.provider.NativePRNG$Blocking.engineNextBytes(NativePRNG.java:268) at java.security.SecureRandom.nextBytes(SecureRandom.java:468) at java.math.BigInteger.randomBits(BigInteger.java:634) at java.math.BigInteger.<init>(BigInteger.java:623) at com.oracle.amc.util.PWUtil.generatePW(PWUtil.java:21) .... Line 21 of method com.oracle.amc.util.PWUtil.generatePW(): ������new BigInteger(130,random).toString(32); Please let me know if you need any other information! Thanks!

Release Note: SecureRandom.PKCS11 from the SunPKCS11 Provider is disabled by default on Solaris because the native implementation has poor performance and is not recommended. If your application requires SecureRandom.PKCS11, you can re-enable it by changing the removing "SecureRandom" from the disabledMechanisms list in conf/security/sunpkcs11-solaris.cfg