JDK-8195743 : FileTreeWalker low performance with SecurityManager installed
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 8,9,10
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows
  • CPU: x86_64
  • Submitted: 2018-01-16
  • Updated: 2025-05-14
  • Resolved: 2025-05-14
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.
Other
tbdResolved
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 10.0.16299.192]

A DESCRIPTION OF THE PROBLEM :
Given a directory with large number of files in it, the Files.walkFileTree method runs exceedingly slower when a SecurityManager is installed.

This is due the fact that the FileTreeWalker implementation drops the cached attributes received from the directory enumeration when a SecurityManager is installed. Looking at the code of FileTreeWalker.getAttributes: (JDK 8 & 9 both have the same source)

        // if attributes are cached then use them if possible
        if (canUseCached &&
            (file instanceof BasicFileAttributesHolder) &&
            (System.getSecurityManager() == null))
        {
            BasicFileAttributes cached = ((BasicFileAttributesHolder)file).get();
            if (cached != null && (!followLinks || !cached.isSymbolicLink())) {
                return cached;
            }
        }

The attribute query only reuses an attribute object when it is allowed to (by canUseCached), and there is no security manager. It is a faulty method, as instead of checking the presence of the security manager, it should check if the security manager allows the reading of the path. This will result in slower performance as the attributes needs to be queried again for every file instead of accessing the one coming from the directory enumeration.

The access check should be done in the following way:

        // if attributes are cached then use them if possible
        if (canUseCached &&
            (file instanceof BasicFileAttributesHolder))
        {
            BasicFileAttributes cached = ((BasicFileAttributesHolder)file).get();
            if (cached != null && (!followLinks || !cached.isSymbolicLink())) {
            	SecurityManager sm = System.getSecurityManager();
            	if(sm != null) {
            		// TODO check read access
            	}
                return cached;
            }
        }

I've selected "Can not make any progress until this bug is resolved." for the severity of the problem as it is impossible to implement high performance I/O application with this bug present.

REGRESSION.  Last worked in version 8u151

ADDITIONAL REGRESSION INFORMATION: 
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the following function on a directory which contains a lot of files. (>50 000)
Run the provided source.

Run the test twice and drop the first result to reduce the impact of any OS level file memory caching.

Output of the program on my computer (with HDD and 50 000 files in the directory):

Without SecurityManager: 690 ms
With SecurityManager: 4666 ms



EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The Files.walkFileTree function should have the same performance, independent of the presence of a SecurityManager.
ACTUAL -
The Files.walkFileTree function runs exceedingly slower when a SecurityManager is present.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
package test;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.security.Permission;

public class SlowTreeWalking {
	private static void enumerateDirectory(Path directory) throws IOException {
		Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
		});
	}

	public static void main(String[] args) throws IOException {
		Path directory = Paths.get("...");
		long nanos = System.nanoTime();
		enumerateDirectory(directory);
		long firstrun = System.nanoTime() - nanos;

		//set dummy security manager
		System.setSecurityManager(new SecurityManager() {
			@Override
			public void checkPermission(Permission perm) {
			}
		});
		nanos = System.nanoTime();
		enumerateDirectory(directory);
		long secondrun = System.nanoTime() - nanos;

		System.out.println("Without SecurityManager: " + firstrun / 1_000_000 + " ms");
		System.out.println("With SecurityManager: " + secondrun / 1_000_000 + " ms");
	}
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Removing the SecurityManager.


Comments
As the SecurityManager has been permanently disabled, this problem no longer exists. In fact the code in FileTreeWalker very much looks like that suggested in the issue description: // if attributes are cached then use them if possible if (canUseCached && (file instanceof BasicFileAttributesHolder bfah)) { BasicFileAttributes cached = bfah.get(); if (cached != null && (!followLinks || !cached.isSymbolicLink())) { return cached; } }
14-05-2025

The security manager is deprecated for removal and the special code paths for running this mode will be removed from the JDK. So it might be the this issue will be closed.
15-09-2024

To reproduce the issue, run the attached test case. JDK 8u151 - Fail JDK 9.0.1+11 - Fail JDK 10-ea+39 - Fail Output on JDK 8u151 : Without SecurityManager: 91286 ms With SecurityManager: 25422103 ms Output on JDK 9.0.1+11 : Without SecurityManager: 38809 ms With SecurityManager: 24984353 ms Output on JDK 10-ea+39 : Without SecurityManager: 83284 ms With SecurityManager: 159862 ms
19-01-2018