On Wed, 29 Apr 2026 23:24:38 GMT, Ashay Rane <[email protected]> wrote:
> On Linux, various `stat()` calls allow probing information about files > without opening them, but until recently, there wasn't an equivalent API > available on Windows. Now that `GetFileInformationByName()` exists, > we can use it instead of `GetFileInformationByHandle()`, which required > first opening the file to create a file handle, then reading the file > attributes, and finally closing the file handle. > > Since `GetFileInformationByName()` is available on only newer versions > of Windows, this patch uses conditional compilation and `LoadLibrary()` > + `GetProcAddress()` to dynamically set the pointer to the API function. > If the dynamic loading fails, we fall back to the old API. To avoid > problems with race conditions, we use Windows' `INIT_ONCE` and > `InitOnceExecuteOnce()` to initialize the function pointer exactly once. > > The rest of the patch is similar to the addition of any new JNI function > call. WindowsConstants.java adds the relevant flags and error codes, > WindowsFileAttributes.java adds the Java entry point, > WindowsNativeDispatcher.java links the Java function with the C > function, and WindowsNativeDispatcher.c calls the Win32 API function. > > --------- > - [x] I confirm that I make this contribution in accordance with the [OpenJDK > Interim AI Policy](https://openjdk.org/legal/ai). Parts of this patch were derived from looking up a similar patch (PR 102149) for CPython (https://github.com/python/cpython) repository. Here is a first pass at a JMH benchmark to show performance improvements. This was run on a Windows/AArch64 machine. Results follow. package org.openjdk.bench.java.nio.file; import java.io.IOException; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Level; import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Warmup; @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MICROSECONDS) @State(Scope.Benchmark) @Fork(value = 3, jvmArgsAppend = {"-Dsun.nio.fs.ensureAccurateMetadata=true"}) @Warmup(iterations = 5, time = 2) @Measurement(iterations = 5, time = 2) public class FileAttributes { Path file; @Setup(Level.Trial) public void setup() throws IOException { file = Files.createTempFile("bench-attrs-", ".tmp"); } @TearDown(Level.Trial) public void cleanup() throws IOException { Files.deleteIfExists(file); } @Benchmark public BasicFileAttributes followLinks() throws IOException { return Files.readAttributes(file, BasicFileAttributes.class); } @Benchmark public BasicFileAttributes noFollowLinks(Blackhole bh) throws IOException { for (Path f : files) { bh.consume(Files.readAttributes(f, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS)); } } } Results: == before == Benchmark Mode Cnt Score Error Units FileAttributes.followLinks avgt 15 22.107 1.976 us/op FileAttributes.noFollowLinks avgt 15 21.425 1.780 us/op == after == Benchmark Mode Cnt Score Error Units FileAttributes.followLinks avgt 15 7.085 0.570 us/op FileAttributes.noFollowLinks avgt 15 7.141 0.648 us/op ------------- PR Comment: https://git.openjdk.org/jdk/pull/30994#issuecomment-4348241548
