Runtime.exec Usage


Runtime.exec Usage

My program calls Runtime.exec(String) to run another external java application, it runs well in windows, but in Linux platform, it always throws error:
The java class is not found:  com/**/MainClass
From the error message, it is obvious that JVM can not find the main class; usually this is because class path is not correctly configured.
But when I paste that string to shell, external program can be successfully started.
After goggle search, I figured out the root cause,
It's recommended to use Runtime.exec(String[]), and add each argument in its own element of the string array. Never add 2 arguments in one element.
Normally, in each element, we should not add ' or ", if we did that, it may cause exception or incorrect value that is not we want.

The following is a sample application to call another java application:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class AppInvoker
{
    public static void main(String[] args)
    {
        try
        {
            String[] cmds = new String[] { "C:\\Program Files\\Java\\jdk1.6.0_23\\bin\\java",
                // with "-ms64m -mx512m", it would fail: Invalid initial heap size: -Xms64m -mx512m
                "-ms64m",
                "-mx512m",
                // if -Dfoo='D:\java projects', the foo value would be 'D:\java projects'
                // if -Dfoo=\"D:\\java projects\", java.lang.ClassNotFoundException: projects, projects would be thought as main class.
                // with "-Dfoo=D:\\java projects -Dbar=bar", value of foo would be - D:\java projects -Dbar=bar -.,
                // bar is null, as it's not set.
                "-Dfoo=D:\\java projects",
                "-Dbar=bar",
                "-classpath",
                // don't add ' before classpath, otherwise it will throw ClassNotFoundException.
                // "" is ok.
                // safe way is to not add ' or " at all.
                "D:\\java projects\\arguments.jar",
                "CommandArguments",
                "-nickname",
                // with 'johnny depp', then value of nickname would be 'johnny depp'.
                // with \"johnny depp\", then value of nickname is still johnny depp.
                "johnny depp",
                "-user",
                "depp",
                "-passwd",
                "depp",
                "-cfg",
                "D:\\java projects\\my.cfg" };

            final Process p = Runtime.getRuntime().exec(cmds);

            // read input stream
            new Thread()
            {
                public void run()
                {
                    try
                    {
                        BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
                        String line;
                        while ((line = in.readLine()) != null)
                        {
                            System.out.println(line);
                        }
                    }
                    catch (Exception e)
                    {
                        e.printStackTrace();
                    }
                };
            }.start();

            // read error stream
            new Thread()
            {
                public void run()
                {
                    try
                    {
                        BufferedReader errReader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
                        String line;
                        while ((line = errReader.readLine()) != null)
                        {
                            System.err.println(line);
                        }
                    }
                    catch (Exception e)
                    {
                        e.printStackTrace();
                    }
                };
            }.start();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
}

public class CommandArguments
{
    public static void main(String[] args)
    {
        // ready system property
        System.out.println("foo:" + System.getProperty("foo"));
        System.out.println("bar:" + System.getProperty("bar"));
        System.out.println("infile:" + System.getProperty("infile"));
        // read parameters
        for (int i = 0; i < args.length; i++)
        {
            System.out.println("args[" + i + "] = " + args[i]);
        }
    }
}

From JDK5, it's recommended to use ProcessBuilder, which provides more functions and deal with spaces much better than Runtime.exec().


Labels

adsense (5) Algorithm (69) Algorithm Series (35) Android (7) ANT (6) bat (8) Big Data (7) Blogger (14) Bugs (6) Cache (5) Chrome (19) Code Example (29) Code Quality (7) Coding Skills (5) Database (7) Debug (16) Design (5) Dev Tips (63) Eclipse (32) Git (5) Google (33) Guava (7) How to (9) Http Client (8) IDE (7) Interview (88) J2EE (13) J2SE (49) Java (186) JavaScript (27) JSON (7) Learning code (9) Lesson Learned (6) Linux (26) Lucene-Solr (112) Mac (10) Maven (8) Network (9) Nutch2 (18) Performance (9) PowerShell (11) Problem Solving (11) Programmer Skills (6) regex (5) Scala (6) Security (9) Soft Skills (38) Spring (22) System Design (11) Testing (7) Text Mining (14) Tips (17) Tools (24) Troubleshooting (29) UIMA (9) Web Development (19) Windows (21) xml (5)