Paths.get() / Path.of() throws NullPointerException on upgrade to Java 16
Asked Answered
L

2

7

When upgrading from Java 15 to Java 16, some of my unit tests began failing due to a null pointer exception. The issue was caused by a null value being passed to the Paths.get() api. What changed in Java 16 to make this an error?

I am using OpenJDK version 16.0.2 and am running on macos.

Leigha answered 15/8, 2021 at 12:52 Comment(0)
L
2

It is an expected exception where first argument of Paths.get() or Path.of() is null. There was a known bug which is fixed as part of Java 16 release.
Bug: link

This is mentioned in the Jdk 16 release notes as well. link

(fs) NullPointerException Not Thrown When First Argument to Path.of or Paths.get Is null (JDK-8254876)
core-libs/java.nio The var args form of Path.of() and Paths.get() method are changed in this release to throw NullPointerException consistently when the first parameter is null. Historically these methods missed a null check on the first parameter when invoked with more than one parameter.

Code flow:

  1. Paths.get calls Path.of internally. (Paths.java)

     public static Path get(String first, String... more) {
         return Path.of(first, more);
     }
    
  2. Path.of code . (Path.java)

    public static Path of(String first, String... more) {
     return FileSystems.getDefault().getPath(first, more);
    }
    
  3. Then as per the file system it calls the suitable getPath method.
    a. WindowsFileSystem
    b. UnixFileSystem

  4. In that method we have a check which confirms that first parameter/path is not null

    Objects.requireNonNull(first);
    
  5. When the first parameter is null then NPE is thrown. (Objects.java)

    public static <T> T requireNonNull(T obj, String message) {
     if (obj == null)
         throw new NullPointerException(message);
     return obj;
    }
    
Landgraviate answered 21/8, 2021 at 12:40 Comment(0)
L
18

As of Java 16, the implementation of Paths.get(), which internally calls Path.of(), now explicitly requires the 'first' path element to be non-null.

This is an implementation change from Java 15, but is consistent with the specification. The package javadoc for java.nio.files states "Unless otherwise noted, passing a null argument to a constructor or method of any class or interface in this package will cause a NullPointerException to be thrown."

This implementation change can be considered and improvement because it will no longer hide the string value "null" appearing in file system paths, which is likely not the desired outcome.

In this case, a unit test was breaking because of an improperly initialized mock object.

Leigha answered 15/8, 2021 at 12:52 Comment(1)
Just to add that this is a corner case for when the first argument is null. The release note for the change in JDK 16 is here: oracle.com/java/technologies/javase/…Equal
L
2

It is an expected exception where first argument of Paths.get() or Path.of() is null. There was a known bug which is fixed as part of Java 16 release.
Bug: link

This is mentioned in the Jdk 16 release notes as well. link

(fs) NullPointerException Not Thrown When First Argument to Path.of or Paths.get Is null (JDK-8254876)
core-libs/java.nio The var args form of Path.of() and Paths.get() method are changed in this release to throw NullPointerException consistently when the first parameter is null. Historically these methods missed a null check on the first parameter when invoked with more than one parameter.

Code flow:

  1. Paths.get calls Path.of internally. (Paths.java)

     public static Path get(String first, String... more) {
         return Path.of(first, more);
     }
    
  2. Path.of code . (Path.java)

    public static Path of(String first, String... more) {
     return FileSystems.getDefault().getPath(first, more);
    }
    
  3. Then as per the file system it calls the suitable getPath method.
    a. WindowsFileSystem
    b. UnixFileSystem

  4. In that method we have a check which confirms that first parameter/path is not null

    Objects.requireNonNull(first);
    
  5. When the first parameter is null then NPE is thrown. (Objects.java)

    public static <T> T requireNonNull(T obj, String message) {
     if (obj == null)
         throw new NullPointerException(message);
     return obj;
    }
    
Landgraviate answered 21/8, 2021 at 12:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.