Tilde expansion (the leading ~) is a feature of the shell. You are not invoking java through a shell, so that is not happening. Use the System.getProperty("user.home") method to find the user's home directory and build the command using that instead of the tilde.

Answer from Jim Garrison on Stack Overflow
🌐
DZone
dzone.com › coding › java › running a java class as a subprocess
Running a Java Class as a Subprocess
May 21, 2019 - Learn more about how to run a Java class as a subprocess in this quick demonstration, specifically by creating a new process from within a test.
Discussions

Executing a Java application in a separate process - Stack Overflow
Can a Java application be loaded in a separate process using its name, as opposed to its location, in a platform independent manner? I know you can execute a program via ... Process process = Run... More on stackoverflow.com
🌐 stackoverflow.com
multithreading - How can I start a 'main' in a new process in Java? - Stack Overflow
I'll answer here how to create multi process application without spring :). With spring you can do this by xml config. Multithread is another story, this is multi-process · Create a JavaProces class as seen below. You can store a counterparter XML/JSON of this class in your environment. Then start ... More on stackoverflow.com
🌐 stackoverflow.com
runtime - Running a java program from another java program - Stack Overflow
Equally, you need to consume any output from the process at the same time. waitFor will block so you will need use a Thread to read the input (and if you need to, write output to the process) Depending on the location of the java/class file, you may also need to specify a starting folder from ... More on stackoverflow.com
🌐 stackoverflow.com
How to create a process in Java - Stack Overflow
@HH: as I said, you'd start it just like you start any Java program via the command line: "java -cp classpath package.name.MainClass". but "compile the code as a separate application" does not make much sense, of course it needs to be compiled, but Java does not really have the concept of "applications" as distinct entities. 2010-01-05T12:58:20.93Z+00:00 ... Hi Michael, you didn't mentioned about "ProcessBuilder" in your answer, which is another ... More on stackoverflow.com
🌐 stackoverflow.com
Top answer
1 of 9
85

This is a synthesis of some of the other answers that have been provided. The Java system properties provide enough information to come up with the path to the java command and the classpath in what, I think, is a platform independent way.

public final class JavaProcess {

    private JavaProcess() {}        

    public static int exec(Class klass, List<String> args) throws IOException,
                                               InterruptedException {
        String javaHome = System.getProperty("java.home");
        String javaBin = javaHome +
                File.separator + "bin" +
                File.separator + "java";
        String classpath = System.getProperty("java.class.path");
        String className = klass.getName();

        List<String> command = new LinkedList<String>();
        command.add(javaBin);
        command.add("-cp");
        command.add(classpath);
        command.add(className);
        if (args != null) {
            command.addAll(args);
        }

        ProcessBuilder builder = new ProcessBuilder(command);

        Process process = builder.inheritIO().start();
        process.waitFor();
        return process.exitValue();
    }

}

You would run this method like so:

int status = JavaProcess.exec(MyClass.class, args);

I thought it made sense to pass in the actual class rather than the String representation of the name since the class has to be in the classpath anyways for this to work.

2 of 9
47

Two hints:

System.getProperty("java.home") + "/bin/java" gives you a path to the java executable.

((URLClassLoader) Thread.currentThread().getContextClassLoader()).getURL() helps you to reconstruct the classpath of current application.

Then your EXECUTE.application is just (pseudocode):

Process.exec(javaExecutable, "-classpath", urls.join(":"), CLASS_TO_BE_EXECUTED)

Top answer
1 of 5
9

Creating a new "java" process from java is not possible since two processes can't share one JVM. (See this question and the accepted answer).


If you can live with creating a new Thread instead of a Process you can do it with a custom ClassLoader. It is as close you can get to a new process. All static and final fields will be reinitialized!

Also note that the "ServerStart class (for the example below) must be in the class path of the current executing JVM):

public static void main(String args[]) throws Exception {
    // start the server
    start("ServerStart", "arg1", "arg2");
}

private static void start(final String classToStart, final String... args) {

    // start a new thread
    new Thread(new Runnable() {
        public void run() {
            try {
                // create the custom class loader
                ClassLoader cl = new CustomClassLoader();

                // load the class
                Class<?> clazz = cl.loadClass(classToStart);

                // get the main method
                Method main = clazz.getMethod("main", args.getClass());

                // and invoke it
                main.invoke(null, (Object) args);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }).start();
}

And this is the custom class loader:

private static class CustomClassLoader extends URLClassLoader {
    public CustomClassLoader() {
        super(new URL[0]);
    }

    protected java.lang.Class<?> findClass(String name) 
    throws ClassNotFoundException {
        try{
            String c = name.replace('.', File.separatorChar) +".class";
            URL u = ClassLoader.getSystemResource(c);
            String classPath = ((String) u.getFile()).substring(1);
            File f = new File(classPath);

            FileInputStream fis = new FileInputStream(f);
            DataInputStream dis = new DataInputStream(fis);

            byte buff[] = new byte[(int) f.length()];
            dis.readFully(buff);
            dis.close();

            return defineClass(name, buff, 0, buff.length, (CodeSource) null);

        } catch(Exception e){
            throw new ClassNotFoundException(e.getMessage(), e);
        }
    }
}
2 of 5
8

Assuming a new thread with a new classloader is not enough (I would vote for this solution though), I understand you need to create a distinct process that invokes a main method in a class without having that declared as "jar main method" in the manifest file -- since you don't have a distinct serverstart.jar anymore.

In this case, you can simply call java -cp $yourClassPath your.package.ServerStart, as you would do for running any java application when you don't have (or don't want to use) the manifest Main-Class.

Top answer
1 of 5
22

It is a bit strange but you can run the second program without forking it. Just calling the main method in it. So forget the runtime section and do this:

sam2.main(new String[0]);

Of course this way you must compile sam2 at compile time

2 of 5
15

Each process needs to be allowed to run and finish. You can use Process#waitFor for this purpose. Equally, you need to consume any output from the process at the same time. waitFor will block so you will need use a Thread to read the input (and if you need to, write output to the process)

Depending on the location of the java/class file, you may also need to specify a starting folder from which the execution of the process can start.

Most of this significantly easier using ProcessBuilder

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

public class CompileAndRun {

    public static void main(String[] args) {
        new CompileAndRun();
    }

    public CompileAndRun() {
        try {
            int result = compile("compileandrun/HelloWorld.java");
            System.out.println("javac returned " + result);
            result = run("compileandrun.HelloWorld");
        } catch (IOException | InterruptedException ex) {
            ex.printStackTrace();
        }
    }

    public int run(String clazz) throws IOException, InterruptedException {        
        ProcessBuilder pb = new ProcessBuilder("java", clazz);
        pb.redirectError();
        pb.directory(new File("src"));
        Process p = pb.start();
        InputStreamConsumer consumer = new InputStreamConsumer(p.getInputStream());
        consumer.start();

        int result = p.waitFor();

        consumer.join();

        System.out.println(consumer.getOutput());

        return result;
    }

    public int compile(String file) throws IOException, InterruptedException {        
        ProcessBuilder pb = new ProcessBuilder("javac", file);
        pb.redirectError();
        pb.directory(new File("src"));
        Process p = pb.start();
        InputStreamConsumer consumer = new InputStreamConsumer(p.getInputStream());
        consumer.start();

        int result = p.waitFor();

        consumer.join();

        System.out.println(consumer.getOutput());

        return result;        
    }

    public class InputStreamConsumer extends Thread {

        private InputStream is;
        private IOException exp;
        private StringBuilder output;

        public InputStreamConsumer(InputStream is) {
            this.is = is;
        }

        @Override
        public void run() {
            int in = -1;
            output = new StringBuilder(64);
            try {
                while ((in = is.read()) != -1) {
                    output.append((char) in);
                }
            } catch (IOException ex) {
                ex.printStackTrace();
                exp = ex;
            }
        }

        public StringBuilder getOutput() {
            return output;
        }

        public IOException getException() {
            return exp;
        }
    }
}

Now obviously, you should check the return results of the processes, and may be produce a better mechanism for interacting with the processes, but that's the basic idea...

Find elsewhere
🌐
David Lim
davidlim2007.wordpress.com › 2016 › 12 › 22 › a-simple-java-program-to-run-another-java-program
A Simple Java Program To Run Another Java Program. – David Lim
December 22, 2016 - The exit value can help us determine // whether the external process ended successfully. int iProcessExitValue = theProcess.exitValue(); System.err.println("Process [" + args[0] + "] ended. Exit value : [" + iProcessExitValue + "]" ); // read from the called program's standard output stream // For an explanation on the strange concept of Java External Process Input Stream, // refer to : // http://stackoverflow.com/questions/32612717/java-process-getoutputstream-to-string try { inStream = new BufferedReader(new InputStreamReader(theProcess.getInputStream())); String line; while ((line = inStream.readLine()) != null) { System.out.println (line); } } catch(IOException e) { System.err.println("Error on inStream.readLine()"); e.printStackTrace(); return false; } // read from the called program's standard error stream.
🌐
Reddit
reddit.com › r/javahelp › how to run another jar from my main program and do input and output
r/javahelp on Reddit: How to run another jar from my main program and do input and output
July 7, 2021 -

I have a jar file that is usually run from a batch file and cannot be run by itself. Is there a way I can run this jar file without editing it from my main jar file.

The secondary file is produced by someone who is not me and I do not have its source code, I am allowed to use it though.

I looked it up and found URLClassLoader which may work but from the batch file that normally runs the jar the command includes memory allocation (Xmx, Xms) Can URLCLassLoader do this?

And also can I get the output from that jar, which is just to a terminal window, to display in my main window and can I pass inputs to it from my main window?

I hope this makes sense. Thanks for any help.

Top answer
1 of 2
2
What you first need to understand is that everytime you run a java process, java will run what's called a Java Virtual Machine (JVM) that's responsible for interpreting the java bytecode generated during the compilation of a java source file. When you try to execute a jar file from the command line, you can provide java with additional parameters (beyond the jar's filename). Some of those parameters define how the JVM operates (in your case Xmx and Xms define the amount of memory that will be allocated on the heap). That said, when you use URLClassLoader to load bytecode at runtime what happens is that the bytecode will be executed by the existing JVM and not by a new one. In other URLClassLoader doesn't create a new process and, consequently, a new JVM. So no, you can't provide values to control how memory allocation is performed. For you, this means that you have two options: either you provide your main program with the memory allocation options that you want your "second program" (remember, URLClassLoader doesn't create a new process nor a new JVM) to use; or you use the classes Process and ProcessBuilder and pipe the input and output streams. https://www.baeldung.com/java-process-api has a basic introduction to those classes and even has a small example on how you can get, from you main process, the output of the subprocess and how you can pass input from you main process to the subprocess.
2 of 2
1
Please ensure that: Your code is properly formatted as code block - see the sidebar (About on mobile) for instructions You include any and all error messages in full You ask clear questions You demonstrate effort in solving your question/problem - plain posting your assignments is forbidden (and such posts will be removed) as is asking for or giving solutions. Trying to solve problems on your own is a very important skill. Also, see Learn to help yourself in the sidebar If any of the above points is not met, your post can and will be removed without further warning. Code is to be formatted as code block (old reddit: empty line before the code, each code line indented by 4 spaces, new reddit: https://imgur.com/a/fgoFFis ) or linked via an external code hoster, like pastebin.com, github gist, github, bitbucket, gitlab, etc. Please, do not use triple backticks (```) as they will only render properly on new reddit, not on old reddit. Code blocks look like this: public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); } } You do not need to repost unless your post has been removed by a moderator. Just use the edit function of reddit to make sure your post complies with the above. If your post has remained in violation of these rules for a prolonged period of time (at least an hour), a moderator may remove it at their discretion. In this case, they will comment with an explanation on why it has been removed, and you will be required to resubmit the entire post following the proper procedures. To potential helpers Please, do not help if any of the above points are not met, rather report the post. We are trying to improve the quality of posts here. In helping people who can't be bothered to comply with the above points, you are doing the community a disservice. I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.
Top answer
1 of 2
2

As on your request I summarize my comments in an answer.

Your first problem was that you tried to invoke java.exe on a Linux or Mac box, which does not stick to the Microsoft convention of including the file type into the name. Therefore Linux and Mac usually use java instead.

The path to the executable can vary also from computer to computer. Therefore the probably most generic way is to locate the java executable using the JAVA_HOME environment variable which can be fetched in Java via System.getenv("JAVA_HOME"); or via System.getProperty("java.home"); Note however that they might not obviously point to the desired directory. Especially some Linux distributions place all binary files inside /bin or /usr/bin and therefore ${JAVA_HOME}/bin/java might not be available. In that case you should create a (hard)link to the executable.

If the path is not set you can set it manually in the session of your console you are executing your application (on Windows set JAVA_HOME=C:\Program Files\Java (or setx on newer Windows versions) on Linux export JAVA_HOME=/opt/java). This can also be done with user-priviledges

It is further strongly recommended to take care of in- and output-streams when dealing with processes. The linked article explains in depth why you should take care of it - not only to catch exceptions thrown by the invoked process.

On invoking a process (especially with the Java executable) you have a couple of options: You can either invoke the Java process directly (assuming Java is on your PATH) with new ProcessBuilder("java", "-cp", "path/to/your/binaries", "package.ClassName"); or you can invoke the Java executable via a shell - on Linux f.e. you could also use new ProcessBuilder("/bin/bash", "-c", "java -cp path/to/your/binaries package.ClassName"); (though the primer one is obviously preferable).

On loading classes/libraries dynamically you have to use the fully qualified class name. So, if you invoke the Java process in the root-directory of your project and your building-tool generates the class-files inside of ./build/classes and your class Test is located in package testpackage you will end up with the following set: ./build/classes/testpackage/Test.class. To start a new Java process which invokes the main method included in your Test.class you have to use the following command: java -cp ./build/classes testpackage.Test else Java will not be able to find the class definition of Test and execute the main-method.

Missing dependencies have to be added to the classpath (-cp ...) segment of the invoking Java command. F.e: java -cp lib/jar1.jar;lib/jar2.jar;build/classes/* package.ClassName. Multiple archives or directories are separated by a ; and an asterisk * is also possible to include everything within a directory.

One note left: if you ever try to ship your "application" you will need to adapt this code to a more generic version (property file f.e) as this will probably fail with high probability as the path might be totally different.

If I have something forgotten, please let me know.

2 of 2
0

Did you try to run java.exe from command prompt if it does not work there as well you need to set you java path to the JAVA Installation this can be done by setting variable JAVA_PATH in system variables and this should point to your Jdk bin folder.

If this does not wok then I think you need to provide full path to JAVA.exe as the program is trying to find this file and it is not able to find the file and it gives error

On contrary you can try making threads that would be a better solution because threads use less resources and are more efficient

🌐
Quora
quora.com › Is-it-possible-to-start-an-external-JVM-process-using-Java-that-is-not-attached-to-the-calling-thread
Is it possible to start an external JVM process using Java that is not attached to the calling thread? - Quora
Answer (1 of 2): Using ProcessBuilder proved to be the most reliable way to do it. [code] ProcessBuilder pb = new ProcessBuilder("standalone.bat"); Map env = pb.environment(); env.put("JAVA_HOME", javaHome); env.put("JAVA_OPTS", javaOpts); pb.directory(new File(workingDir)); pb.s...
Top answer
1 of 3
38

http://www.rgagnon.com/javadetails/java-0014.html

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.file.Paths;

public class CmdExec {

public static void main(String args[]) {
    try {
        // enter code here

        Process p = Runtime.getRuntime().exec(
            Paths.get(System.getenv("windir"), "system32", "tree.com /A").toString()
        );

        // enter code here

        try(BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
            String line;

            while ((line = input.readLine()) != null) {
                System.out.println(line);
            }
        }

    } catch (Exception err) {
        err.printStackTrace();
    }
  }
}

You can get the local path using System properties or a similar approach.

http://download.oracle.com/javase/tutorial/essential/environment/sysprop.html

2 of 3
31

The Java Class Library represents external processes using the java.lang.Process class. Processes can be spawned using a java.lang.ProcessBuilder:

Process process = new ProcessBuilder("processname").start();

or the older interface exposed by the overloaded exec methods on the java.lang.Runtime class:

Process process = Runtime.getRuntime().exec("processname");

Both of these will code snippets will spawn a new process, which usually executes asynchronously and can be interacted with through the resulting Process object. If you need to check that the process has finished (or wait for it to finish), don't forget to check that the exit value (exit code) returned by process.exitValue() or process.waitFor() is as expected (0 for most programs), since no exception is thrown if the process exits abnormally.

Also note that additional code is often necessary to handle the process's I/O correctly, as described in the documentation for the Process class (emphasis added):

By default, the created subprocess does not have its own terminal or console. All its standard I/O (i.e. stdin, stdout, stderr) operations will be redirected to the parent process, where they can be accessed via the streams obtained using the methods getOutputStream(), getInputStream(), and getErrorStream(). The parent process uses these streams to feed input to and get output from the subprocess. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, or even deadlock.

One way to make sure that I/O is correctly handled and that the exit value indicates success is to use a library like jproc that deals with the intricacies of capturing stdout and stderr, and offers a simple synchronous interface to run external processes:

ProcResult result = new ProcBuilder("processname").run();

jproc is available via maven central:

<dependency>
      <groupId>org.buildobjects</groupId>
      <artifactId>jproc</artifactId>
      <version>2.5.1</version>
</dependency>
Top answer
1 of 3
2

If this is for testing purposes, just launch the other process from the command line or use Eclipse to take care of it. In Eclipse the same project can have multiple main() entry points. When you wish to run the app you create a run / debug configuration that says which entry point you wish to invoke. So you could define one for the client and one for the server and run them with a button click.

Expanded:

Prerequisite - import your project into Eclipse first before doing any of this.

  1. Run Eclipse from the Java perspective (which is normally the case for a Java project)
  2. You will see two toolbar buttons marked Debug As... and Run As.... I will describe the Debug button from now on but the same principle applies to Run As..
  3. Next to the Debug As... button is a drop down button. Click it and from the drop down choose Debug Configurations...
  4. A configuration dialog will open. In the Dialog double click on "Java Application". Eclipse will create a new debug configuration for debugging a Java application.
  5. Use the fields on the right to choose which Eclipse project you are debugging, the main class (i.e. the one with the static main you wish to invoke) and any other args you want to set. You can give your configuration a meaningful name and apply the changes.
  6. Create two configurations one for your client and one for your server, e.g. "debug client" and "debug server"
  7. Exit the dialog
  8. Now the Debug As... drop down contains two actions with your new configurations. You can click them to launch your apps in debug mode. You will observe that each instance is running in a separate java.exe process.

Eclipse also has a debug perspective where you can stop / pause running processes, set breakpoints and whatnot. It can even debug more than one thing simultaneously so you could launch both client and server in debug and set breakpoints either side of the call.

2 of 3
1

Java allows you to make system calls like so.

 Runtime r = Runtime.getRuntime();
 Process p = r.exec("java otherMain arg0 arg1");

This would allow you to start another java process. Process also has methods to get the output of that process if you need it.

🌐
CodingTechRoom
codingtechroom.com › question › -start-another-java-application
How to Start Another Java Application from a Java Program - CodingTechRoom
ProcessBuilder processBuilder = new ProcessBuilder("java", "-jar", "path/to/your/app.jar"); processBuilder.start(); In Java, you can start another Java application using the `ProcessBuilder` or `Runtime.exec()` method. Both options allow you to run a separate Java application while your current ...
🌐
DigitalOcean
digitalocean.com › community › tutorials › compile-run-java-program-another-java-program
How to Compile and Run Java Program from another Java Program | DigitalOcean
August 4, 2022 - Let’s write a simple java program that will be compiled and run from another java program. package com.journaldev.files; public class Test { public static void main(String[] args) { System.out.println("Start"); for(String str : args){ System.out.println(str); } } }
🌐
Dot Net Perls
dotnetperls.com › process-java
Java - Process, ProcessBuilder Examples - Dot Net Perls
September 16, 2024 - And one process, in a Java program, cannot contain another one. But with ProcessBuilder, in java.lang.ProcessBuilder, we construct and invoke operating system commands. We launch external processes—like EXEs. This program creates an instance of ProcessBuilder. It then calls command() to set the command. We use two arguments: two strings. Detail We pass a variable number of arguments to command—it combines these strings into a command string. Start With start we invoke the command.
🌐
Baeldung
baeldung.com › home › java › core java › guide to java.lang.process api
Guide to java.lang.Process API | Baeldung
June 10, 2025 - The Process class provides methods for interacting with these processes, including extracting output, performing input, monitoring the lifecycle, checking the exit status, and destroying (killing) it. First, let’s see an example to compile and run another Java program with the help of the ...