Home > Enterprise >  java.lang.IllegalArgumentException in the program after building in jar
java.lang.IllegalArgumentException in the program after building in jar

Time:07-03

I have an exe file in a JavaFX project that I launch on a button click. Works fine in IDE, but if you build in jar it stops working and throws this error - java.lang.IllegalArgumentException: The file: src\main\resources\com\application\exeServices\SetProcessWorkingSetSize.exe doesn't exist.

the project hierarchy

The code I call exe

private void useCleaningService() {
    final String path = "src/main/resources/com/application/exeServices/SetProcessWorkingSetSize.exe";
    File file = new File(path);
    try {
        Desktop.getDesktop().open(file);
    } catch (Exception e){
        System.out.println(e);
    }
}

CodePudding user response:

First of all check if file exists with exists() function, you obviously using wrong file path in your jar

CodePudding user response:

Preface: This answer assumes you're using the "standard directory layout" of Maven/Gradle, based on the presence of src/main/java and src/main/resources.


Files under src/main/resources are resources, not files. This means you have to access them using the resource-lookup API. For example:

URL url = getClass().getResource("/com/application/exeServices/SetProcessWorkingSetSize.exe");

This will give you a URL pointing to your resource, and it will do this in an application-location-independent way. In other words, it finds the resource on the class-path/module-path. If you want to read the resource then you'd open an InputStream using URL#openStream() (or get an InputStream directory by using Class#getResourceAsStream(String)). Note that resources are read-only. Also, notice the above does not include src/main/resources in the path. That directory only exists in your project's development environment; it does not exist after deployment (nor does it exist in your build output).

As previously stated, resources are not files. This means you can't read them using the File API. This is especially true once you package your application into a JAR file or custom run-time image, because File has no idea how to read the packaged resource.

But you have another problem. I strongly doubt Windows is capable of executing an executable file when it's packaged in a JAR file or custom run-time image. Just like the File API of Java, Windows has no idea how to read packaged Java resources. You'd have to extract the resource into a regular file, and then have Windows execute that file. For example:

// uses java.nio.file.Path and java.nio.file.Files
private void useCleaningService() {
  Path exe = Path.of(System.getProperty("user.home"), ".app_name", "SetProcessWorkingSetSize.exe");
  try {
    if (Files.notExists(exe)) {
      try (InputStream in = getClass().getResourceAsStream("/com/application/exeServices/SetProcessWorkingSetSize.exe")) {
        Files.createDirectories(exe.getParent());
        Files.copy(in, exe);
      }
    }
    Desktop.getDesktop().open(exe.toFile());
  } catch (Exception ex) {
    ex.printStackTrace();
  }
}

This will extract the executable file to an application-specific directory (replace .app_name with the whatever name you want for that directory) in the user's home directory (e.g., C:\Users\<username>). It will only perform the extraction if the target file doesn't already exist. This will prevent unnecessary work, but as currently implemented, it will also prevent replacing the executable with new versions of it (unless you change the name of the target file). So, depending on your needs, you might want to modify the code to extract the resource once per application instance.

  • Related