Search code examples
javanio

Java 9: How to retrieve the ctime in FileVisitor.visitFile()?


I'm looking for an efficient way to retrieve the ctime information stored in sun.nio.fs.UnixFileAttributes during a Files.walkFileTree:

Files.walkFileTree(root, EnumSet.noneOf(FileVisitOption.class), Integer.MAX_VALUE, new FileVisitor<Path>() {
  public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
    // get ctime from BasicFileAttributes here
  }
}

There is a hack for Java 8: reflection can be used to access UnixFileAttributes.ctime(). However this code requires to change accessibility of the ctime()-method which will fail for Java 9 with an InaccessibleObjectException.

Class<?> basicFileAttributesClass = Class.forName("java.nio.file.attribute.BasicFileAttributes");
Class<?> unixFileAttributesClass = Class.forName("sun.nio.fs.UnixFileAttributes");

Method toUnixFileAttributesMethod = unixFileAttributesClass.getDeclaredMethod("toUnixFileAttributes", basicFileAttributesClass);
toUnixFileAttributesMethod.setAccessible(true);

Method cTimeMethod = unixFileAttributesClass.getDeclaredMethod("ctime");
cTimeMethod.setAccessible(true);

Object unixFileAttributes = toUnixFileAttributesMethod.invoke(unixFileAttributesClass, attributes);
((FileTime)cTimeMethod.invoke(unixFileAttributes)).toMillis();

I'm still hoping to have missed some NIO utility method which does the job.


Solution

  • For Java 9 and up, the setAccessible() checks module permissions, which your module doesn't have. This can be unlocked with the VM option --add-opens java.base/sun.nio.fs=ALL-UNNAMED.