1

The following command runs correctly in my Linux terminal:

java -Djava.library.path=/home/john/native_so_libraries/linux-64 -cp '/home/john/NetBeansProjects/SendReceive/dist/SendReceive.jar:/home/j‌​ohn/Desktop/Dropbox/Libjitsi_linux_64/*' Main "send"

This command specifies a folder for native .so libraries (via Djava.library.path=/...), an application JAR file named "SendReceive.jar", a folder for JAR libraries (via the -cp classpath option), and also a main class containing a main method to run, a class called "Main". It has as one command line argument surrounded by quotation marks, the "send" argument. This command works and runs a Java process from the terminal, but I cannot figure out how to get it to work with Runtime.getRuntime().exec from another process.

Note that I am doing my best to follow the instructions provided in this tutorial: http://www.javaworld.com/article/2071275/core-java/when-runtime-exec---won-t.html?page=2 - meaning that I am using threads to consume the standard input and standard error streams from the process. Still, the process won't start when I make that terminal command into a string like so:

Process process = Runtime.getRuntime().exec("java -Djava.library.path=/home/john/native_so_libraries/linux-64 -cp '/home/john/NetBeansProjects/SendReceive/dist/SendReceive.jar:/home/j‌​ohn/Desktop/Dropbox/Libjitsi_linux_64/*' Main \"send\"");

How do I make this command run via Runtime.getRuntime().exec?

2 Answers2

3

The short answer is don't. Use ProcessBuilder instead. It allows you to separate each command line parameter into it's own String and this will appear as a separate "argument" to the process. This makes it really useful for dealing with paths that have spaces in them, for instance...

ProcessBuilder pb = new ProcessBuilder(
                "java", 
                "-Djava.library.path=/home/johnmichaelreed/Desktop/Dropbox/Libjitsi_linux_64/lib/native/linux-64", 
                "-cp", 
                "/home/johnmichaelreed/NetBeansProjects/SendReceive/dist/SendReceive.jar:/home/j‌​ohnmichaelreed/Desktop/Dropbox/Libjitsi_linux_64", 
                "Main", 
                "\"send\"");

pb.redirectErrorStream(true);
try {
    Process p = pb.start();
    try (InputStream is = p.getInputStream()) {
        int in = -1;
        while ((in = is.read()) != -1) {
            System.out.print((char)in);
        }
    }
    int exitCode = p.exitValue();

    System.out.println("Process exited with " + exitCode);
} catch (IOException ex) {
    ex.printStackTrace();
}

It also allows you to redirect the stderr into the stdout which makes it easier to read.

You should also read the stdout and check the exit values for better digansotics

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
1

The first thing you'll need to do is perform the glob (represented by * in your classpath). You can also use a ProcessBuilder - which is used to create operating system processes. And, a List<String> or command(s), and a StringBuilder to perform the glob. Something like,

public static void main(String[] args) {
    String home = System.getProperty("user.home");
    System.out.println(home);
    List<String> command = new ArrayList<>();
    command.add("java");
    command.add("-Djava.library.path=" + home
            + "/native_so_libraries/linux-64");
    StringBuilder cp = new StringBuilder();
    cp.append(home + "/NetBeansProjects/SendReceive/dist/SendReceive.jar");
    try {
        File dir = new File(home + "/Desktop/Dropbox/"
                + "Libjitsi_linux_64/");
        for (File f : dir.listFiles()) {
            if (f.isFile()) {
                cp.append(":").append(f.getCanonicalPath());
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    command.add("-cp");
    command.add(cp); // <-- shouldn't need literal
                    // single quotes.
    command.add("Main");
    command.add("send"); // <-- shouldn't need literal double quotes.
    ProcessBuilder pb = new ProcessBuilder(command);
    pb.inheritIO();
    try {
        Process p = pb.start();
        System.exit(p.waitFor());
    } catch (Exception e) {
        e.printStackTrace();
    }
}
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • 1
    Shouldn't `command.add("-cp " + cp.toString())` be to separate parameters, otherwise it will be presented to the process as a single argument, when it's expecting two... – MadProgrammer May 19 '15 at 01:15