9

I'm facing a strange behaviour of the JVM. I wanted to change the user directory, i.e. the dir where files are looked up, that normally corresponds to the path where the java command is run.

So I wrote the following code:

System.setProperty("user.dir", "/tmp/");
File f = new File("myfile");
System.out.println(f.exists());
System.out.println(f.getCanonicalFile().exists());

The file /tmp/myfile exists and is readable by the JVM, but if I'm not in /tmp/ when I run that code, the result is:

false
true

They are the same file, Java is able to retrieve the correct canonical form of it, but the relative one does not exist, while the canonical one exists.

Is it a bug? Is there a way to reliably change the JVM user directory?

Changing the code is not an option, as I'm trying to run external libraries.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
Nicola Ferraro
  • 4,051
  • 5
  • 28
  • 60
  • Are you sure that the change of System variables is immediately recognised by the JVM? – J Fabian Meier Jun 20 '16 at 08:39
  • 2
    You can try to override it during startup with -Duser.dir=/tmp/. I suppose that somewhere in native filesystem code this information is being cached early. I don't think it is something which should be changed during runtime - how existing File instances should behave in such case? – Artur Biesiadowski Jun 20 '16 at 08:40
  • Just FWIW, I've been able to verify the behavior. The documentation of `exists` is really quite minimal; it doesn't say it's going to resolve a relative path before checking and, well, apparently it doesn't. – T.J. Crowder Jun 20 '16 at 08:46
  • 1
    http://stackoverflow.com/questions/840190/changing-the-current-working-directory-in-java - Changing the working directory using `System.setProperty()` or giving jvm argument is not guaranteed to work. – Codebender Jun 20 '16 at 08:47

1 Answers1

5

This behavior is normal, the reason is, there is a difference between

File f = new File("myfile");

and

File cf = new File("myfile").getCanonicalFile();

The first denotes a filepath relative to your current WORKING DIR, which could be your project path. Using the relative path, the user.dir property is NOT USED, even when setting user.dir as JVM parameter -Duser.dir=/tmp/. The resolution of Java file handles to native file entities is done natively by the underlying Fileystem implementation.

But when invoking getCanoncialFile() before resolving the native file handle the relative path is resolved using the user path information - in your case user.dir = /tmp/.

Apparently, there is no file myfile in <WORKING_DIR> but in /tmp/.

The behavior is the same for f.getAbsoluteFile().

Gerald Mücke
  • 10,724
  • 2
  • 50
  • 67