Execute another jar in a Java program

JavaJarExecutable Jar

Java Problem Overview


I had written several simple java applications named as A.jar, B.jar.

Now i want to write a GUI java program so that user can press button A to execute A.jar and button B to execute B.jar.

Also i want to output the run-time process detail in my GUI program.

Any suggestion?

Java Solutions


Solution 1 - Java

If I understand correctly it appears you want to run the jars in a separate process from inside your java GUI application.

To do this you can use:

// Run a java app in a separate system process
Process proc = Runtime.getRuntime().exec("java -jar A.jar");
// Then retreive the process output
InputStream in = proc.getInputStream();
InputStream err = proc.getErrorStream();

Its always good practice to buffer the output of the process.

Solution 2 - Java

.jar isn't executable. Instantiate classes or make call to any static method.

EDIT: Add Main-Class entry while creating a JAR.

>p.mf (content of p.mf)

>Main-Class: pk.Test

>Test.java

package pk;
public class Test{
  public static void main(String []args){
    System.out.println("Hello from Test");
  }
}

Use Process class and it's methods,

public class Exec
{
   public static void main(String []args) throws Exception
    {
        Process ps=Runtime.getRuntime().exec(new String[]{"java","-jar","A.jar"});
        ps.waitFor();
        java.io.InputStream is=ps.getInputStream();
        byte b[]=new byte[is.available()];
        is.read(b,0,b.length);
        System.out.println(new String(b));
    }
}

Solution 3 - Java

Hope this helps:

public class JarExecutor {

private BufferedReader error;
private BufferedReader op;
private int exitVal;

public void executeJar(String jarFilePath, List<String> args) throws JarExecutorException {
	// Create run arguments for the

	final List<String> actualArgs = new ArrayList<String>();
	actualArgs.add(0, "java");
	actualArgs.add(1, "-jar");
	actualArgs.add(2, jarFilePath);
	actualArgs.addAll(args);
	try {
		final Runtime re = Runtime.getRuntime();
		//final Process command = re.exec(cmdString, args.toArray(new String[0]));
		final Process command = re.exec(actualArgs.toArray(new String[0]));
		this.error = new BufferedReader(new InputStreamReader(command.getErrorStream()));
		this.op = new BufferedReader(new InputStreamReader(command.getInputStream()));
		// Wait for the application to Finish
		command.waitFor();
		this.exitVal = command.exitValue();
		if (this.exitVal != 0) {
			throw new IOException("Failed to execure jar, " + this.getExecutionLog());
		}

	} catch (final IOException | InterruptedException e) {
		throw new JarExecutorException(e);
	}
}

public String getExecutionLog() {
	String error = "";
	String line;
	try {
		while((line = this.error.readLine()) != null) {
			error = error + "\n" + line;
		}
	} catch (final IOException e) {
	}
	String output = "";
	try {
		while((line = this.op.readLine()) != null) {
			output = output + "\n" + line;
		}
	} catch (final IOException e) {
	}
	try {
		this.error.close();
		this.op.close();
	} catch (final IOException e) {
	}
	return "exitVal: " + this.exitVal + ", error: " + error + ", output: " + output;
}
}

Solution 4 - Java

The following works by starting the jar with a batch file, in case the program runs as a stand alone:

public static void startExtJarProgram(){
        String extJar = Paths.get("C:\\absolute\\path\\to\\batchfile.bat").toString();
        ProcessBuilder processBuilder = new ProcessBuilder(extJar);
        processBuilder.redirectError(new File(Paths.get("C:\\path\\to\\JavaProcessOutput\\extJar_out_put.txt").toString()));
        processBuilder.redirectInput();
        try {
           final Process process = processBuilder.start();
            try {
                final int exitStatus = process.waitFor();
                if(exitStatus==0){
                    System.out.println("External Jar Started Successfully.");
                    System.exit(0); //or whatever suits 
                }else{
                    System.out.println("There was an error starting external Jar. Perhaps path issues. Use exit code "+exitStatus+" for details.");
                    System.out.println("Check also C:\\path\\to\\JavaProcessOutput\\extJar_out_put.txt file for additional details.");
                    System.exit(1);//whatever
                }
            } catch (InterruptedException ex) {
                System.out.println("InterruptedException: "+ex.getMessage());
            }
        } catch (IOException ex) {
            System.out.println("IOException. Faild to start process. Reason: "+ex.getMessage());
        }
        System.out.println("Process Terminated.");
        System.exit(0);
    }

In the batchfile.bat then we can say:

@echo off
start /min C:\path\to\jarprogram.jar

Solution 5 - Java

If the jar's in your classpath, and you know its Main class, you can just invoke the main class. Using DITA-OT as an example:

import org.dita.dost.invoker.CommandLineInvoker;
....
CommandLineInvoker.main('-f', 'html5', '-i', 'samples/sequence.ditamap', '-o', 'test')

Note this will make the subordinate jar share memory space and a classpath with your jar, with all the potential for interference that can cause. If you don't want that stuff polluted, you have other options, as mentioned above - namely:

  • create a new ClassLoader with the jar in it. This is more safe; you can at least isolate the new jar's knowledge to a core classloader if you architect things with the knowledge that you'll be making use of alien jars. It's what we do in my shop for our plugins system; the main application is a tiny shell with a ClassLoader factory, a copy of the API, and knowledge that the real application is the first plugin for which it should build a ClassLoader. Plugins are a pair of jars - interface and implementation - that are zipped up together. The ClassLoaders all share all the interfaces, while each ClassLoader only has knowledge of its own implementation. The stack's a little complex, but it passes all tests and works beautifully.
  • use Runtime.getRuntime.exec(...) (which wholly isolates the jar, but has the normal "find the application", "escape your strings right", "platform-specific WTF", and "OMG System Threads" pitfalls of running system commands.

Solution 6 - Java

First we cerate a class FirstFileOutput having a main method that outputs a line to stable output and a line to stable error. With all first procedure, we'll again create a class RuntimeExecCheck that will run our FirstFileOutput class in starting for process, and after that RuntimeExecCheck class will read the stable output and the stable error from FirstFileOutput and output comes.

package check;

public class FirstFileOutput{

	public static void main(String[] args) {
		System.out.println("This is output to stable output");
		System.err.println("This is output to stable error");
	}
}



package check;

import java.io.InputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class RuntimeExecCheck {

	public static void main(String[] args) {
		try {
			Runtime runTime = Runtime.getRuntime();
			Process process = runTime.exec("java -classpath C:\\projects\\workspace\\check\\bin check.FirstFileOutput");
			InputStream inputStream = process.getInputStream();
			InputStreamReader isr = new InputStreamReader(inputStream);
			InputStream errorStream = process.getErrorStream();
			InputStreamReader esr = new InputStreamReader(errorStream);

			int n1;
			char[] c1 = new char[1024];
			StringBuffer stableOutput = new StringBuffer();
			while ((n1 = isr.read(c1)) > 0) {
				stableOutput.append(c1, 0, n1);
			}
			System.out.println("Stable Output: " + stableOutput.toString());

			int n2;
			char[] c2 = new char[1024];
			StringBuffer stableError = new StringBuffer();
			while ((n2 = esr.read(c2)) > 0) {
				stableError.append(c2, 0, n2);
			}
			System.out.println("Stable Error: " + stableError.toString());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

Solution 7 - Java

If you are java 1.6 then the following can also be done:

import javax.tools.JavaCompiler; 
import javax.tools.ToolProvider; 

public class CompilerExample {
    
    public static void main(String[] args) {
        String fileToCompile = "/Users/rupas/VolatileExample.java";
        
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        
        int compilationResult = compiler.run(null, null, null, fileToCompile);
        
        if (compilationResult == 0) {
            System.out.println("Compilation is successful");
        } else {
            System.out.println("Compilation Failed");
        }
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionwinsontan520View Question on Stackoverflow
Solution 1 - JavagjrwebberView Answer on Stackoverflow
Solution 2 - JavaKV PrajapatiView Answer on Stackoverflow
Solution 3 - JavaSwarvanu SenguptaView Answer on Stackoverflow
Solution 4 - JavaDawood F.M KaundamaView Answer on Stackoverflow
Solution 5 - JavaFordiView Answer on Stackoverflow
Solution 6 - JavaForce BoltView Answer on Stackoverflow
Solution 7 - JavarupaView Answer on Stackoverflow