JDK-8047769 : SecureRandom should be more frugal with file descriptors
  • Type: Bug
  • Component: security-libs
  • Sub-Component: java.security
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux_ubuntu
  • CPU: x86
  • Submitted: 2014-06-22
  • Updated: 2015-08-26
  • Resolved: 2015-01-21
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.
JDK 9
9 b48Fixed
Related Reports
Duplicate :  
Relates :  
Description
If I run this java program on Linux

public class SecureRandoms {
    public static void main(String[] args) throws Throwable {
        new java.security.SecureRandom();
    }
}

it creates 6 file descriptors for /dev/random and /dev/urandom, as shown by:

strace -q -ff -e open java SecureRandoms |& grep /dev/
[pid 20769] open("/dev/random", O_RDONLY) = 5
[pid 20769] open("/dev/urandom", O_RDONLY) = 6
[pid 20769] open("/dev/random", O_RDONLY) = 7
[pid 20769] open("/dev/random", O_RDONLY) = 8
[pid 20769] open("/dev/urandom", O_RDONLY) = 9
[pid 20769] open("/dev/urandom", O_RDONLY) = 10

Looking at jdk/src/solaris/classes/sun/security/provider/NativePRNG.java
it looks like 2 file descriptors are created for every variant of NativePRNG, whether or not they are ever used.  Which is wasteful.  In fact, you only ever need at most two file descriptors, one for /dev/random and one for /dev/urandom.

Further, it would be nice if the file descriptors were closed when idle and lazily re-created.  Especially /dev/random should typically be used at startup and never thereafter.
Comments
Assigning to Peter, code is out for review in the Dec 2014 thread. http://mail.openjdk.java.net/pipermail/security-dev/2014-December/011521.html
30-12-2014

The current code in the Sun Provider initialization is to see if NativeNonBlocking/NativeBlocking is ok (isAvailable()) is dragging in the various files. This should be reworked to only pull in /dev/random,urandom once. if (NativePRNG.Blocking.isAvailable()) { map.put("SecureRandom.NativePRNGBlocking", "sun.security.provider.NativePRNG$Blocking"); } if (NativePRNG.NonBlocking.isAvailable()) { map.put("SecureRandom.NativePRNGNonBlocking", "sun.security.provider.NativePRNG$NonBlocking"); }
16-12-2014

For /dev/random itself ... as the "blocking" naming suggests, there are implementations where getting bytes from NativePRNGBlocking might "hang" for multiple seconds, so should only ever be used when explicitly requested and getting very high quality randomness. So for generateSeed etc, I would actually open-read-close every time the user requested data instead of keeping a file descriptor open. For "low-quality" randomness as required by ThreadLocalRandom, seeding from /dev/urandom is enough, but others will repeatedly e.g. call SecureRandom.nextBytes repeatedly, so keeping a file descriptor open is more reasonable. On some OSes, /dev/random and /dev/urandom have identical semantics, and it's never useful to open both. It's tricky to implement idling-out of non-memory resources in Java. I'm not aware of a best-practices cookbook way of doing this. The reduction from 6 long-term file descriptors to 1 is lower-hanging fruit.
23-06-2014

I was positive there was already a bug for this, but for the life of me I can't find it now. There's some other more minor cleanup that needs to take place. I use this bug until I can find the other, then combine any issues. If there was no bug, then we'll just use this one.
23-06-2014