3

I am trying to create a launcher for a Java application that will automatically update/download a jar file in the user home area of a computer, and then proceed to execute it.

I've tried to run the jar file using both the Process and Runtime classes, and I've had nothing but success on my own pc, but it seems that 1:10 people that try this distributed software (also in jar form) can't seem to have the jar file to run (for reference I have ensured that all the people who tested this application had the newest version of Java installed).

The code responsible for running the jar file is as follows:

 public static void startApplication() {
        try {
             Process proc = Runtime.getRuntime().exec("java -jar "+(saveDirectory + fileName));
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

I expected for the jar file fileName to be opened in location saveDirectory, however in a pc to pc scenario this wasn't always the case. I'm just wondering if there is perhaps a better way of doing this that will ensure success 100% of the time.

Danny
  • 65
  • 5
  • Are you escaping spaces in `saveDirectory` variable? – Karol Dowbecki Jan 16 '19 at 15:51
  • The saveDirectory variable is as follows: `private static String saveDirectory = System.getProperty("user.home")+"/";` for additional reference the fileName variable is as follows: `private static String fileName = "Client.jar";` – Danny Jan 16 '19 at 15:52

2 Answers2

3

If user.home contains spaces this may not work as the command is evaluated as-is due to being provided as String. Use the Runtime.exec(String[]) version:

Runtime.getRuntime().exec(new String[] { "java", "-jar", saveDirectory + fileName });

Additionally you may want to normalize the JAR path:

Path path = Paths.get(saveDirectory, fileName);
String fullPath = path.normalize().toAbsolutePath().toString();
Runtime.getRuntime().exec(new String[] { "java", "-jar", fullPath });
Karol Dowbecki
  • 43,645
  • 9
  • 78
  • 111
  • Thank you for your answer. Could you just clarify what you mean by user.home containing spaces, so that I can gain a better understanding of the issue? Would it also be recommended to instead use a ProcessBuilder like so: `ProcessBuilder pb = new ProcessBuilder("java", "-jar", saveDirectory + fileName); Process p = pb.start();` – Danny Jan 16 '19 at 15:59
  • `java -jar C:\User\myself\My Documents\Downloads\app.jar` will fail because `C:\User\myself\My` is not a JAR location and `Documents\Downloads\app.jar` is not a `main()` argument. The space is the sparator for `java -jar` syntax. – Karol Dowbecki Jan 16 '19 at 16:02
  • Thank you for the clarification and the help you've provided. – Danny Jan 16 '19 at 16:07
1

Your original code runs under the premise, that "java" is (generaly) available on the "PATH" (or in particular available in the current working dir).

The point of @Karol might also be an issue! (exec(String[]) is waaay better than exec(String))

But a more reliable way to call java/be independent from the existence & content of (OS) 'PATH' variable is, to pre-pend: System.getProperty("java.home")/bin/ to java. (Since this is always set, and has precedence over eventual OS variables) Now you'd only have to pray about PATH_EXT variable. :) (e.g. ".exe;.bat..." in windows) ...but a decent hope there is: there (on the client machine) is at least a jvm installed and running! :)

And to make your program even more portable, you should replace all /s and \s (platform dependent path separators) with:

System.getProperty("file.separator");

[3]

xerx593
  • 12,237
  • 5
  • 33
  • 64