The current working directory in Java is the folder from which we started the java command, and Java stores it in the system property user.dir. To get it, we call System.getProperty(“user.dir”), which returns a String, or Path.of(“”).toAbsolutePath(), which returns a Path.
We need the working directory whenever the code uses a relative path, such as config/app.properties or logs/app.log, because Java resolves every relative path against that folder.
The following example shows the ways to get the working directory on Java 25. We start the program in the folder /home/lokesh/demo, and the result of each line is in the comment.
String userDir = System.getProperty("user.dir"); // /home/lokesh/demo
Path cwd = Path.of("").toAbsolutePath(); // /home/lokesh/demo
Path cwdPaths = Paths.get("").toAbsolutePath(); // /home/lokesh/demo
Path cwdFs = FileSystems.getDefault().getPath("").toAbsolutePath(); // /home/lokesh/demo
String fileEmpty = new File("").getAbsolutePath(); // /home/lokesh/demo
Path dot = Path.of(".").toAbsolutePath(); // /home/lokesh/demo/.
Path dotNormalized = Path.of(".").toAbsolutePath().normalize(); // /home/lokesh/demo
Notice that all five calls return the same folder, whereas the “.” path keeps a trailing /. until we call normalize().
Java has no dedicated method such as getCwd(), so every way in the snippet reads the same user.dir value. Next, we look at when to use each way and how the working directory differs from the location of the JAR file. We also see why changing user.dir at runtime breaks relative paths.
1. Using System.getProperty(“user.dir”)
In Java, user.dir property is the directory where java command was run from. In other words, it outputs the location where the application was started. The JVM sets user.dir at startup from the working directory of the operating system process, and the File Javadoc calls it the “current user directory”.
String currentWorkingDir = System.getProperty("user.dir"); // /home/lokesh/demo
The value depends on where we start the program, not on where the class files are. When we start the same class from the parent folder /home/lokesh, the property changes with it.
cd /home/lokesh/demo
java -cp target/classes com.howtodoinjava.io.CurrentWorkingDirectory
# user.dir = /home/lokesh/demo
cd /home/lokesh
java -cp demo/target/classes com.howtodoinjava.io.CurrentWorkingDirectory
# user.dir = /home/lokesh
So System.getProperty(“user.dir”) returns the root folder of our Java project only when we start the program from that folder. IDEs such as IntelliJ IDEA and Eclipse start the program in the project folder by default, and each run configuration has a “Working directory” field to change it.
The property user.dir is one of the standard Java system properties, so it is always set and never returns null.
2. Using NIO Path.of(“”).toAbsolutePath()
If we are working on Java 7 or higher, a better approach is to use the Path APIs for finding the current working directory. A Path object has methods such as resolve() and getParent(), so we can build other paths from it without string concatenation.
In the given example, Path.of(“”) is used to build an empty relative path, i.e. the working directory itself. The method toAbsolutePath() resolves the empty path against the working directory, so we get the full path.
Path cwd = Path.of("").toAbsolutePath(); // /home/lokesh/demo
Path configFile = cwd.resolve("config").resolve("app.properties"); // /home/lokesh/demo/config/app.properties
boolean exists = Files.exists(configFile); // false
The method Path.of() came in Java 11. In Java 7 to 10, we call Paths.get(“”), which returns the same Path. The longer form FileSystems.getDefault().getPath(“”) also gives the same result, because Path.of() calls it.
2.1. When Do We Need normalize()?
Please do not forget to use normalize()) method when the path starts with “.”. The method toAbsolutePath() only puts the working directory in front of the path, so “.” stays in the result. The method normalize() removes the “.” and “..” parts.
| Code | Result |
|---|---|
| Path.of(“”).toAbsolutePath() | /home/lokesh/demo |
| Path.of(“.”).toAbsolutePath() | /home/lokesh/demo/. |
| Path.of(“.”).toAbsolutePath().normalize() | /home/lokesh/demo |
| new File(“.”).getAbsolutePath() | /home/lokesh/demo/. |
| new File(“.”).getCanonicalPath() | /home/lokesh/demo |
| Path.of(“”).toRealPath() | /home/lokesh/demo |
The last two rows also resolve symbolic links, so they return the real folder on disk. Both methods read the file system and declare a checked IOException, whereas toAbsolutePath() and normalize() only work on the path text. The method toRealPath() throws a NoSuchFileException when the folder does not exist, whereas getCanonicalPath() returns the path anyway.
3. Using new File(“”).getAbsolutePath()
Older code that uses java.io.File can get the working directory from an empty File. The Javadoc of getAbsolutePath() says that the empty pathname returns the current user directory.
String fileEmpty = new File("").getAbsolutePath(); // /home/lokesh/demo
String fileDot = new File(".").getCanonicalPath(); // /home/lokesh/demo (declares IOException)
We use File only when we pass the result to an API that still takes a File. For new code, Path from section 2 is the better choice.
4. Working Directory vs the JAR or Class Location
The working directory and the folder of our JAR file are often different. For example, a scheduler starts a report job with java -jar /opt/reports/report-job.jar from the home folder of the user. The job reads templates/invoice.html with a relative path and fails, because Java looks for the file in the home folder, not in /opt/reports.
When we need the folder of the JAR or of the compiled classes, we ask the class for its code source.
Path codeLocation = Path.of(CurrentWorkingDirectory.class.getProtectionDomain()
.getCodeSource().getLocation().toURI()); // /home/lokesh/demo/target/classes
When the program runs from a JAR, the result is the path of the JAR file itself, so we call getParent() to get its folder. The method toURI() throws the checked URISyntaxException, and converting the URL through a URI handles spaces in the folder name, which URL.getPath() returns as %20.
For files that ship with the app, such as templates, we read them from the classpath instead of the file system. The method getResourceAsStream() finds them inside the JAR, whatever the working directory is, as shown in reading a file from the resources folder.
5. Can We Change the Current Working Directory in Java?
No. Java has no method that changes the working directory of the running JVM process. Calling System.setProperty(“user.dir”, …) only changes the property text, because the JDK reads user.dir once at startup and keeps that value for resolving paths.
String old = System.setProperty("user.dir", "/tmp");
String changed = System.getProperty("user.dir"); // /tmp
String stillOld = new File("x").getAbsolutePath(); // /home/lokesh/demo/x
Path stillOldPath = Path.of("").toAbsolutePath(); // /home/lokesh/demo
Setting -Duser.dir=… on the command line is not a fix either. The classes File and Path resolve against the new value, but the operating system process still runs in the old folder, so FileReader and FileInputStream can open a different file than Files.readString(). In the following run, the program starts in /home/lokesh/demo with -Duser.dir=/home/lokesh/demo/other, and both folders contain a hello.txt file.
FileReader: from the process directory
Files.readString: from user.dir
File.exists: true
The safe way is to start the program in the right folder, or to build absolute paths from a base folder that we pass in as a property, such as -Dapp.home=/opt/reports. When only a child process must run in another folder, we set that folder with ProcessBuilder.directory().
Process process = new ProcessBuilder("pwd")
.directory(new File("/tmp"))
.inheritIO()
.start(); // prints /tmp (pwd exists on Linux and macOS)
int exitCode = process.waitFor(); // 0
6. Conclusion
The current working directory in Java is the folder from which we started the java command. We read it with System.getProperty(“user.dir”) when we need a String, or with Path.of(“”).toAbsolutePath() when we want a Path to build other paths. When the path starts with “.”, we add normalize().
The working directory is not the folder of the JAR file, so files that ship with the app belong on the classpath. We also never change user.dir at runtime or with -Duser.dir, because different Java APIs would resolve the same relative path to different files.
7. References
- System.getProperties() Javadoc (Java 25))
- Path Javadoc (Java 25)
- File Javadoc (Java 25)
- ProcessBuilder Javadoc (Java 25)
- System Properties (The Java Tutorials)
Happy Learning !!