Java's random number implementation has a lot of pits, to record the use of jdk1.8 in the new version of the enhanced random number implementation SecureRandom.getInstanceStrong()
encountered problems.
Prior to the maintenance of ali-tomcat, it was found that the JVM random number algorithm selection caused the SessionID of Tomcat is very slow, you can refer to the JVM on the random number and entropy pool strategy and Docker Apache-tomcat start slow problem these two articles. However, it was not too much, thought that the use of the -Djava.security.egd=file:/dev/./urandom
can be avoided, in this project again encountered random number caused all threads blocked after the discovery of this piece is quite a lot of rules.
jdk1.8 is used in this project, the startup parameters are set
-Djava.security.egd=file:/dev/./urandom
The random number method used is Java8 NEW:
SecureRandom.getInstanceStrong();
When a fault is encountered, the thread blocks
"DubboServerHandler-xxx:20880-thread-1789" #28440 daemon prio=5 os_prio=0 tid=0x0000000008ffd000 nid=0x5712 runnable [0x000000004cbd7000]java.lang.Thread.State: RUNNABLE at 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)
Because this place has locks, the locked <0x00000000c03a3c90>
other threads will wait for this when they call here 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)
To check NativePRNG$Blocking
the code, see its document description:
A Nativeprng-like class, uses/dev/random for both seed and random material. Note that it does isn't respect the EGD properties, since we have no how to knowing what those qualities is.
Strange how the -Djava.security.egd=file:/dev/./urandom
parameters do not work, still use /dev/random
as a random number of entropy pool, long time or frequent calls to the entropy pool is easy enough to cause blocking; so I looked at SecureRandom.getInstanceStrong()
the document:
Returns a SecureRandom object that is selected by using the algorithms/providers specified in the Securerandom.strongalgo Rithms Security property.
Originally has its own algorithm, in the jre/lib/security/java.security
file, the default definition is:
securerandom.strongAlgorithms=NativePRNGBlocking:SUN
If the algorithm value is modified, the logic is used NativePRNGNonBlocking:SUN
NativePRNG$NonBlocking
as the /dev/urandom
entropy pool and the blocking problem is not encountered. But this file is a JDK system file, modify it or reassign a path is a bit of trouble, preferably through the system environment variable to set, but this variable is not like the securerandom.source
property can be configured through the system environment variables -Djava.security.egd=xxx
, looking for a half day is no corresponding system environment variables. Had to change the code, do not use SecureRandom.getInstanceStrong
This new method, changed to SecureRandom.getInstance("NativePRNGNonBlocking")
.
For SecureRandom
the two algorithm implementations: SHA1PRNG
and NativePRNG
securerandom.source
the relationship with the variable, find a very clear explanation of the article: Using the SecureRandom Class
on Linux:1) If this value is ' file:/dev/urandom ' then the NATIVEPRNG algorithm are registered by the Sun crypt o Provider as the default implementation; The NATIVEPRNG algorithm then reads from/dev/urandom for Nextbytes but/dev/random in GenerateSeed2) when this value is "File:/dev/random" then the NATIVEPRNG algorithm was not registered by the Sun crypto provider, and the SHA1PRNG system use s a nativeseedgenerator which reads from/dev/random.3) when this value was anything else then the sha1prng are used with a Urlseedgenerator that reads from this source.4) when the value was undefined, then sha1prng was used with Threadedseedgenera TOR5) when the code explicitly asks for "sha1prng" and the value are either "File:/dev/urandom" or "file:/dev/random" then (2) also OCCURS6) when the code explicitly asks for "sha1prng" and the value are some other "file:" URLs, then (3) OCCURS7) When the code explicitly asks for "sha1prng" and the value are undefined then (4) occurs
As for the SHA1PRNG
algorithm, why use Urandom, can not be directly set to be used in a file:/dev/urandom
flexible way to set as file:///dev/urandom
or file:/dev/./urandom
, refer to here:
In Sha1prng, there are a seedgenerator which does various things depending on the configuration.
If Java.security.egd or Securerandom.source point to "file:/dev/random" or "file:/dev/urandom", we'll use Nativeseedgene Rator, which calls Super () which calls Seedgenerator.urlseedgenerator (/dev/random). (A nested class within Seedgenerator.) The only things that changed in this bug is that Urandom would also trigger use of this code path.
If Those properties point to another URLs that exists, we'll initialize Seedgenerator.urlseedgenerator (URL). This was why "File:///dev/urandom", "file:/./dev/random", etc. 'll work.
http://hongjiang.info/java8-nativeprng-blocking/
Talking about the blocking problem caused by random number