web-dev-qa-db-ja.com

Javaプログラムで別のjarを実行する

A.jar、B.jarという名前の簡単なJavaアプリケーションをいくつか作成しました。

次に、ユーザーがボタンAを押してA.jarを実行し、ボタンBを押してB.jarを実行できるように、GUI Javaプログラムを作成します。

また、GUIプログラムでランタイムプロセスの詳細を出力したい。

なにか提案を?

102
winsontan520

私の理解が正しければ、Java GUIアプリケーションの内部から別のプロセスでjarを実行したいようです。

これを行うには、次を使用できます。

// 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();

プロセスの出力をバッファすることは常に良い習慣です。

59
gjrwebber

.jarは実行可能ではありません。クラスをインスタンス化するか、静的メソッドを呼び出します。

編集:JARの作成中にMain-Classエントリを追加します。

> 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));
    }
}
22
adatapost

お役に立てれば:

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;
}
}
13

Jarがクラスパスにあり、そのメインクラスがわかっている場合は、メインクラスを呼び出すことができます。例としてDITA-OTを使用する:

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

これにより、下位jarがメモリスペースとクラスパスをjarと共有し、干渉を引き起こす可能性のあるすべての可能性があることに注意してください。そのようなものを汚染したくない場合は、上記のように他のオプションがあります-すなわち:

  • jarを含む新しいClassLoaderを作成します。これはより安全です。エイリアンのjarを使用するという知識で物事を設計すれば、少なくとも新しいjarの知識をコアクラスローダーに分離できます。私の店ではプラグインシステムのために何をしますか。メインアプリケーションは、ClassLoaderファクトリ、APIのコピー、および実際のアプリケーションがClassLoaderを構築する最初のプラグインであるという知識を持つ小さなシェルです。プラグインは、一緒に圧縮されたjar(インターフェースと実装)のペアです。 ClassLoaderはすべてすべてのインターフェイスを共有しますが、各ClassLoaderは独自の実装に関する知識しか持っていません。スタックは少し複雑ですが、すべてのテストに合格し、美しく動作します。
  • Runtime.getRuntime.exec(...)を使用します(jarを完全に分離しますが、通常の「アプリケーションを見つける」、「文字列をエスケープする」、「プラットフォーム固有のWTF」、および実行中のシステムコマンドの「OMGシステムスレッド」の落とし穴があります。
0
Fordi

プログラムがスタンドアロンとして実行される場合、バッチファイルで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
0
Dawood Morris