¿Cómo obtener la ubicación actual de un JAR en Java?

Advertisements

Es una tarea común en las aplicaciones requerir interactuar con archivos ubicados en una ruta relativa desde donde se ejecuta la aplicación. En el caso de Java, no hay una API específica para obtener ese valor, sin embargo, hay muchas formas de obtenerlo de forma sencilla. Vamos a verlos.

System.Property

Cuando ejecutamos una aplicación Java, tiene muchas propiedades pobladas por defecto por la JVM, una de ellas es la propiedad "user.dir", y su valor contiene el “directorio de trabajo del usuario“, que en la mayoría de los casos tendrá el directorio del ejecutable jar.

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

APIS de File y NIO Files

Otro enfoque es usar la API de archivos para obtener el directorio actual, usando la ruta relativa "." o una ruta relativa vacía, debería devolver la ubicación actual del ejecutable.

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

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

La ruta relativa “vacío” o "." usará internamente el directorio de trabajo actual del usuario. Por lo tanto, devolverá el mismo valor que el enfoque "user.dir“.

Cuando la ruta no es la esperada para la ubicación del JAR

Hay algunas situaciones en las que los valores devueltos por los enfoques anteriores no devuelven el valor esperado donde se encuentra el JAR.

Advertisements
  • En Linux, ejecute el archivo jar abriéndolo desde el Explorador de archivos (por ejemplo, haga doble clic en el archivo jar). Devolverá el directorio de inicio del usuario, independientemente de la ubicación donde se encuentre el jar.
  • En Windows, en algunas versiones antiguas, ejecutar jar desde la línea de comando con “Permisos de usuario administrador” podría devolver "C://windows/system32"

Esto se debe a que el directorio de trabajo del usuario indicado por el sistema podría no ser la ubicación del jar. Por ejemplo, en el explorador de archivos de Linux, aunque hayamos navegado por las carpetas y la ruta sea diferente al directorio de inicio, cuando se ejecute el JAR, la propiedad “user.dir” contendrá el directorio de inicio. Esto no ocurrirá al navegar por la línea de comandos, porque el comando cd anulará el directorio de trabajo del usuario.

Para ese propósito, podemos usar el siguiente fragmento de código:

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

La primera línea devolverá la ubicación del archivo jar. La segunda línea obtendrá el directorio contenedor de ese archivo.

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();
  }
}

Con ese bloque de código estático al comienzo de la aplicación, podemos obtener la ubicación real del archivo JAR y anular el valor de la propiedad del sistema "user.dir“. Entonces, podemos usar cualquiera de los otros enfoques en la lógica de la aplicación y ver que el valor es el esperado, independientemente de la forma en que se ejecutó la aplicación (línea de comando, doble clic) o el entorno (Windows, Linux, Mac).

Referencias

Advertisements

Leave a Reply

Your email address will not be published.