How to get the current directory path of a JAR in Java

Advertisements

It’s a common task in applications to require to interact with files located in a relative path from where the application is executed. In the case of Java there isn’t a specific API to get that value, however there are a lot of ways to get the value easily. Let’s see them.

System.Property

When we execute a Java application, it has a lot properties populated by default by the JVM, one of them is the “user.dir” property, and its value contains the “user working directory“, which in most of the cases will have the directory of the jar executable.

String userDirectory = System.getProperty("user.dir");

File and NIO Files API

Another approach is using the Files API to get the current directory, using the relative path "." or an empty relative path, it should return the current location of the executable.

//Using the Old File api
String userDirectory2 = new File("").getAbsolutePath();

//Using Files NIO api
String userDirectory3 = Paths.get("")
        .toAbsolutePath()
        .toString();

The relative “empty” or "." path will use the user current working directory internally. Therefore, it will return the same value as the “user.dir” approach.

When the path value is not the expected JAR location

There are some situations where the values returned by the previous approaches doesn’t return the expected value where the JAR is located.

Advertisements
  • On Linux, running the jar file by opening it from the File Explorer (eg, double click on the jar file). It will return the home directory of the user, regardless of the location where the jar is located.
  • On Windows, in some old versions, running jar from command line with “Admin User permissions” might return “C://windows/system32

This is because the user working directory indicated by the system might not be the jar location. For example, in Linux File explorer even though we have navigated through the folders and the path is different than the home directory, when the JAR is executed the “user.dir” property will contain the home directory. This will not happened when navigating through the command line, because the cd command will override the working directory of the user.

For that purpose we can use following snippet code:

File file = new File(MyClass.class.getProtectionDomain().getCodeSource()
                     .getLocation().toURI().getPath());
String basePath = file.getParent();

The first line will return the location of the jar file. The second line will get the container directory of that file.

public class MyApp {
  
  static {
    //This static block runs at the very begin of the APP, even before the main method.
    try{
      File file = new File(MyApp.class.getProtectionDomain().getCodeSource()
                       .getLocation().toURI().getPath());
      String basePath = file.getParent();
      //Overrides the existing value of "user.dir"
      System.getProperties().put("user.dir", basePath);
    }catch(Exception ex){
      //log the error
    }
  }
 
  public static void main(String args []){
    //Your app logic

    // Use any of the other approaches with the expected value
    String userDirectory = System.getProperty("user.dir");
    String userDirectory2 = new File("").getAbsolutePath();
  }
}

With that static block of code at the very beginning of the application, we can get the real location of the JAR file and override the value of the system property “user.dir“. So, we can use any of the other approaches in the application logic, and see the value is the expected regardless of the way the application was executed (command line, double click) or the environment (Windows, Linux, Mac).

References

Advertisements

Leave a Reply

Your email address will not be published.