JDK-8355342 : File.getCanonicalPath on Java 24 resolves paths on network drives to UNC format
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.io
  • Affected Version: 24,25
  • Priority: P3
  • Status: In Progress
  • Resolution: Unresolved
  • OS: windows
  • CPU: generic
  • Submitted: 2025-04-22
  • Updated: 2025-09-11
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 26
26Unresolved
Related Reports
Causes :  
Description
ADDITIONAL SYSTEM INFORMATION :
OS: Windows 11 Pro 
Locale: Japanese
JDK: OpenJDK 24.0.1 and 24

A DESCRIPTION OF THE PROBLEM :
This method is implementation-dependent, so this may not strictly qualify as a bug. However, I'm reporting it because it seems to be an unintended behavioral change.

Starting with Java 24, on Windows, when passing the path of a file mounted on a network drive (e.g., Z:\a.txt) to File.getCanonicalPath, the path is now automatically resolved to its UNC form (e.g., \\192.168.1.3\...).

UNC paths cannot be used as working directories when launching external processes on Windows (e.g., via Runtime.exec). As a result, this change breaks some existing code that worked correctly in previous Java versions.

While this behavior can be avoided by using the more modern Path.toRealPath instead of File.getCanonicalPath -- which does not expand to UNC paths -- it cannot be avoided in APIs that likely rely internally on File.getCanonicalPath, such as JFileChooser.setDirectory in Swing.

Overall, I believe it would be better for compatibility with existing code if this behavioral change in File.getCanonicalPath were reverted or adjusted.

REGRESSION : Last worked in version 23

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. On Windows, mount a network location as a network drive (e.g., Z:\).

2. Create a File instance pointing to a file or folder on the network drive (e.g., Z:\a.txt).

3-A. Call getCanonicalPath() on the instance and observe the resulting path.

3-B. Alternatively, pass the network drive path to JFileChooser#setDirectory, select a file within the directory, and observe the returned path.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The path on the network drive is returned (e.g., Z:\a.txt).
ACTUAL -
The UNC path is returned instead (e.g., \\192.168.1.3\share-directory\a.txt).

---------- BEGIN SOURCE ----------
import java.io.File;
import java.io.IOException;

public class ReportExample {

    public static void main(String[] args) throws IOException {

        // When the network drive "Z:" is mounted,
        // and "a.txt" exists on that drive,
        // create a File instance pointing to it.
        java.io.File file = new File("Z:\\a.txt");

        // Use the target method to retrieve the path.
        String path = file.getCanonicalPath();

        // Print the result.
        System.out.println("Retrived path: " + path);

        // Java 24 (if a.txt exists): \\192.168.1.3\share-directory\a.txt
        // Java 24 (if a.txt does NOT exist): Z:\a.txt
        // Java 23: Z:\a.txt
    }
}
---------- END SOURCE ----------


Comments
In java.io.WinNTFileSystem.canonicalize(), the result of canonicalize0() is passed to GetFinalPathNameByHandleW() with flags value zero which is equivalent to FILE_NAME_NORMALIZED|VOLUME_NAME_DOS. If the canonicalized path starts with the letter of a mapped drive, this function converts the drive letter to "\\?\", i.e., "\\server\share\..." syntax. This use of GetFinalPathNameByHandleW was added by the change made for JDK-8003887 in JDK 24 build 15, hence the behavioral difference with respect to JDK 23.
11-09-2025

I mounted the location \\localhost\c$\Temp on drive letter Z:. For the existing file Z:\junk.txt for the Path jshell> Path p = Path.of("Z:\\junk.txt") p ==> Z:\junk.txt JDK 23 gives jshell> p.toFile().getCanonicalPath() $2 ==> "Z:\\junk.txt" whereas JDK 24 and 26-internal give $2 ==> "\\\\localhost\\c$\\Temp\\junk.txt" For toRealPath they all give jshell> p.toRealPath() $3 ==> Z:\junk.txt
11-09-2025

This is a likely side effect of the change made for JDK-8003887.
25-06-2025

I think we need to get the output of Path::toRealPath on Z:\test.zip to see what it produces.
24-04-2025

Impact -> H (Regression) Likelihood -> L (Probably not an issue) Workaround -> M (Somewhere in-between the extremes) Priority -> P3
23-04-2025

The observations on Windows 11: JDK 24+14: Passed, the output is Z:\test.zip, the same as previous JDKs. JDK 24+15: Failed, the output becomes \\wsl$\Ubuntu-20.04\test.zip JDK 25ea+6: Failed.
23-04-2025