6

I want to test if a file exists on a mounted network drive.

I wrote this simple code using File.exists.

import java.io.File;

public class NetworkDrive {
    public static void main(String[] args) {
        System.err.println(new File("/Volumes/DATA/testedFile.txt").exists());
    }
}

It works correctly mostly but i found an edge case where this code is problematic. If the drive was mounted and for some reason the network connection fails down, the program hangs for a very long time (10 minutes).

time java NetworkDrive
false

real    10m6.114s
user    0m0.431s
sys 0m0.949s

Even if i try to kill it using with a KILL signal, the process is still running.

1875 ttys000    0:00.00 (java)

The problem is the same with java.nio:

Files.exists(Paths.get("/Volumes/DATA/testedFile.txt"));

I use java version 1.8.0_20 on OS X Yosemite.

gontard
  • 28,720
  • 11
  • 94
  • 117
  • Although it shouldn't change much, have you tried with `java.nio.file.Files#exists()`? – fge Feb 02 '15 at 13:52
  • @fge, yes. It was my first tentative. – gontard Feb 02 '15 at 13:56
  • Well, stick to java.nio.file then. This is 2015, you should drop File anyway – fge Feb 02 '15 at 14:05
  • I am sorry but it fails with both. I have exactly the same problem with: `Files.exists(Paths.get("/Volumes/DATA/testedFile.txt"))` – gontard Feb 02 '15 at 14:13
  • Yes, I understood that, this was not my point; my point is, if you use java.nio.file, drop File usage. File has a load of problems which java.nio.file doesn't. – fge Feb 02 '15 at 14:18
  • Yes you are right. And it is what i have done in almost all my application. But sometimes, i have to deal with `java.io.File`: http://docs.oracle.com/javase/8/javafx/api/javafx/stage/FileChooser.html#setInitialDirectory-java.io.File- – gontard Feb 02 '15 at 14:22

2 Answers2

3

The File#exists method in java is just a wrapper around a native O/S call which is what is taking that long. My suggestion would be to implement a timeout in your program; assuming that the file does not exist if the call does not return within a shorter time. Simple timeout in java notes a possible way of doing that.

EDIT: The fact that you cannot kill the thread even with a KILL signal shows that the system call is uninterruptible. This is a problem of the O/S and cannot be solved in Java. While it does prevent the program from ending while the call is running (even if you mark the thread as a daemon), you can still work around it by executing the call in another thread: that way, you can assume the call has failed after a shorter timeout in your main thread and carry on with program execution, even if the call is still running in the background.

Community
  • 1
  • 1
Adrian Leonhard
  • 7,040
  • 2
  • 24
  • 38
  • Yes i tried to run this code in another thread with a timeout. It works... mostly. But for example, the thread is not responding, so i can't quit the application. – gontard Feb 02 '15 at 14:17
  • @DavidZimmerman is referring to daemon threads, which will not prevent the JVM from exiting. You could do this by passing the ThreadFactory defined in http://stackoverflow.com/q/7158587/1980909 as a second argument to the `Executors#newScheduledThreadPool` call in the simple timeout example. – Adrian Leonhard Feb 02 '15 at 14:39
  • @AdrianLeonhard i have also tried with a daemon thread. The thread is not responding at all, keeping my application alive. – gontard Feb 02 '15 at 15:15
  • If you are unable to kill the thread/process from the O/S (which is what you tried to do with the KILL signal if I understand correctly) it could mean that the file system call is uninterruptible... if this is the case, the problem cant be resolved with Java. Do other applications stop responding if they try accessing the problematic network drive? – Adrian Leonhard Feb 02 '15 at 15:50
  • @AdrianLeonhard oh well spotted ! I have the same problem with a simple `tail -f /Volumes/DATA/testedFile.txt`. Could you update your answer and i will accept it ! Thanks even if my problem is not solved... at least the diagnostic is better. – gontard Feb 03 '15 at 08:35
1

The File class relies heavily on the local filesystem without knowing that there is some sort of network behind it. If you want to keep the application responsive you can try to call new File("/Volumes/DATA/testedFile.txt").exists() from another Thread.

Hope this helps.

Andrey E
  • 856
  • 8
  • 18
  • This is what i have tried. It works... mostly. But for example, the background thread is no responding, so i can't quit the application. – gontard Feb 02 '15 at 14:09
  • You can work around that by making the thread a daemon thread (setDaemon(true)) – Gimby Feb 02 '15 at 15:14