JDK-6705872 : SecureRandom number init is taking too long on a java.io.tmpdir with a large number of files.
  • Type: Bug
  • Component: security-libs
  • Sub-Component: java.security
  • Affected Version: 6u10,6u16,6u29
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic,windows_xp,windows_vista
  • CPU: generic,x86
  • Submitted: 2008-05-21
  • Updated: 2011-11-30
  • Resolved: 2011-05-02
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 7
7 b51Fixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Description
The excerpt below from an email from a customer (see the Comments section for details) indicates a performance problem with Cipher.getInstance() the first time it is run after rebooting a Windows system. Apparently it is calling File.list() in java.io.tmpdir, which at a high level seems unnecessary and causes major performance issues on machines with a large number of files in the system's temporary directory. See the attachment for a test case from the customer.

If investigation indicates that this is a problem in the deployment technologies or the extension class loader, please indicate this and we can reassign the bug to the appropriate team.

--------
About two weeks ago I was informed that some of our machines were pausing for an extended period of time partway through start up of our applets. The startup delay appeared to be specific to certain machines and to the first use of our applets after system boot. I investigated (luckily one of the machines affected was my own!)  and what I discovered was that the initial call to ���Cipher.getInstance()��� was taking upto 30 seconds to complete. Subsequent calls to Cipher.getInstance() were fractions of a millisecond. I examined stack traces taken during the pause and determined that the system was busy doing a File.list() call.

It appears that during the loading of lib/ext/sunjce_provider.jar a File.list() is executed against the java.io.tmpdir. On Windows XP this property references the user���s ���Local Settings\Temp\��� directory. Since this directory is used as a dumping ground for numerous applications is contents are unpredictable. What I discovered on my machine was that it contained 11000+ files.

I tried doing a dos-level listing on that directory just after a boot and found that just listing the files was taking about 30 seconds.

To further confirm the problem I wrote some functions that I have attached. The test program wraps three behaviors

1) adding 50,000 files to a temp directory.
2) measuring the time it takes to List and FileList(fileFilter) those files,
3) measure the time it takes to run Cipher.getInstance().

(Sorry, didn���t write any cleanup code to remove the files.)

I also set up the functions so that an alternate directory could be specified to java.io.tmpdir at run time. There are batch files included to exercise each behavior.

The results of running these tests follow:

CipherBuilder: Cipher.getInstance()
  at boot with 50000 files     - 101207.88 ms
  post boot with 50000 files ��� 678 ms
  at boot with no files          ��� 902 ms
  post boot with no files      - 350 ms

MeasureTempFiles: File.list()
  at boot with 50000 files     ��� 104264.64 ms
  post boot with 50000 files ��� 209 ms

I have put a workaround into our code to add a java-specific directory to the standard java.io.tmpdir path and that fixes the problem for our signed jars. The same approach won���t work for unsigned jars.

Although this only happens at first use after bootup, it is a significant and unexpected performance hit. I don���t know whether the File.list() function is needed as part of the ext jar loading procedure since I don���t have access to this code, but it might seem to be a good idea, in general, to have the java.io.tmpdir point to a directory that was not as prone to filling with ���foreign��� files.
--------

Comments
EVALUATION http://hg.openjdk.java.net/jdk7/tl/jdk/rev/a8d9e8cb38bb
04-03-2009

EVALUATION Fixed using the NIO2 Path.newDirectoryStream() method. At most 1024 files are used. No regression test, need a special arrage of TMP dir.
04-03-2009

EVALUATION Copied from evaluation of 4285834: This issue has been addressed by the file system API defined for NIO2. A DirectoryStream is returned when the directory is opened and this can be used to iterate over the entries in a huge directory without requiring the read the entire list of file names as is done by the File.list method. Entry 3 alan.bateman [2008-02-01 10:48]
27-05-2008

EVALUATION The original synopsis was: First call to Cipher.getInstance() is too slow This is most likely due to the SecureRandom number generator intialization code. As part of the setup, the implementation needs to collect some entropy for use as a seed. Among other things (current time/strings in memory/memory usage stats), it looks at the tmpdir to collect additional info. Maybe this should be adjusted to consider a maximum number of files, or remove this source of entropy completely.
21-05-2008