Search code examples
javalinuxsymlinkfile-descriptor

Resolve broken symbolic links without checking for existance


I have an issue with my Java webapp: it fails after few days with error FileSystemException: Too many open files. I understand what it means, but I can't figure out where I didn't close the file. So I'm trying to write some debug code to help me find the reason of this error: this code is supposed to return all file descriptors (and shows it via debug http endpoint):

Files.list(Paths.get(String.format("/proc/$d/fd", pid))).map(
  fd -> String.format(
    "%s:%s",
    fd.getFileName(),
    // also I tried fd.toRealPath()
    fd.toFile().getCanonicalFile()
  )
).collect(Collectors.toList())

But this code doesn't show broken links (symbolic links where target was removed). Path.toRealPath() fails with NoSuchFileException here, Path.toFile().getCanonicalPath() ignores such links and doesn't show the target. Only system ls -l /proc/$pid/fd/ works correctly and resolve all links.

Is it possible to resolve such links using Java (1.8 JDK)?


Solution

  • Turning my comment into an answer, I can see two options to figure out whether a file is a dead symbolic link:

    1. Use Files.readSymbolicLink() and then check whether the target exists.
    2. Use Files.exists() with different options: If the file exists with NOFOLLOW_LINKS but does not exist without that option then it should be a dangling symbolic link.