Выполнить еще одну банку в программе Java
Я написал несколько простых Java-приложений, названных A.jar, B.jar.
Теперь я хочу написать Java-программу с графическим интерфейсом, чтобы пользователь мог нажать кнопку A, чтобы выполнить A.jar, и кнопку B, чтобы выполнить B.jar.
Также я хочу вывести детали процесса во время выполнения в моей программе с графическим интерфейсом.
Любое предложение?
Ответы
Ответ 1
Если я правильно понял, вы хотите запустить банки в отдельном процессе из вашего приложения GUI для Java.
Для этого вы можете использовать:
// 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();
Его всегда хорошая практика для буферизации вывода процесса.
Ответ 2
.jar не является исполняемым. Выполните активацию классов или вызовите любой статический метод.
EDIT:
Добавьте запись Main-Class при создании JAR.
p.mf(содержание p.mf)
Основной класс: pk.Test
>Test.java
package pk;
public class Test{
public static void main(String []args){
System.out.println("Hello from Test");
}
}
Используйте класс Process и его методы,
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));
}
}
Ответ 3
Надеюсь, что это поможет:
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;
}
}
Ответ 4
Если jar в вашем пути к классам и вы знаете его Основной класс, вы можете просто вызвать основной класс. Использование DITA-OT в качестве примера:
import org.dita.dost.invoker.CommandLineInvoker;
....
CommandLineInvoker.main('-f', 'html5', '-i', 'samples/sequence.ditamap', '-o', 'test')
Обратите внимание, что это приведет к тому, что подчиненное пространство памяти для обмена банками и путь к классу будут объединены с вашей банкой со всеми возможными помехами, которые могут вызывать. Если вы не хотите, чтобы этот материал был загрязнен, у вас есть другие варианты, как указано выше, а именно:
- создайте новый ClassLoader с банкой в нем. Это более безопасно; вы можете, по крайней мере, изолировать новое знание jar до основного загрузчика классов, если вы архитектируете вещи, зная, что вы будете использовать чужие банки. Это то, что мы делаем в моем магазине для нашей системы плагинов; основным приложением является крошечная оболочка с ClassLoader factory, копия API и знание о том, что реальное приложение является первым плагином, для которого он должен построить ClassLoader. Плагины - это пара баннеров - интерфейс и реализация, которые застегиваются вместе. ClassLoaders все используют все интерфейсы, в то время как каждый ClassLoader имеет только знания о своей собственной реализации. Стек немного сложный, но он проходит все тесты и прекрасно работает.
- use
Runtime.getRuntime.exec(...)
(который полностью изолирует банку, но имеет нормальные "найти приложение", "избегать ваших строк справа", "специфичные для платформы WTF" и "ошибки системы OMG" для запуска системных команд.
Ответ 5
Следующее работает, запуская jar с командным файлом, в случае, если программа работает автономно:
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);
}
В batchfile.bat мы можем сказать:
@echo off
start /min C:\path\to\jarprogram.jar
Ответ 6
Если вы java 1.6, то также можно сделать следующее:
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");
}
}
}