Jalankan jar lain dalam program Java


115

Saya telah menulis beberapa aplikasi java sederhana bernama A.jar, B.jar.

Sekarang saya ingin menulis program java GUI sehingga pengguna dapat menekan tombol A untuk mengeksekusi A.jar dan tombol B untuk mengeksekusi B.jar.

Saya juga ingin menampilkan detail proses run-time dalam program GUI saya.

Ada saran?


31
Tidak yakin mengapa ini ditolak. Jelaskan kepadanya mengapa asumsinya mungkin salah, tetapi jangan meremehkan pertanyaan tersebut.
William Brendel

-1 terminologi dasar Java tidak digunakan dengan benar dan pertanyaannya sangat kabur dan meninggalkan banyak tebakan kedua. Pertimbangkan untuk menyusun ulang pertanyaan Anda dengan lebih detail atau cukup baca tentang Java classpath dan dasar-dasar lainnya terlebih dahulu.
topchef

21
@grigory: Lihat, itu yang seharusnya Anda tanyakan di tempat pertama, daripada langsung downvoting. Downvoting tanpa meminta info lebih lanjut tidak ada gunanya ...
William Brendel

4
@William, maaf telah menekan tombol beberapa detik lebih lambat dari yang Anda lakukan. Saya berhak untuk memilih dengan komentar berikutnya. Sangat menjengkelkan melihat pertanyaan diajukan tanpa persiapan dasar dan / atau upaya untuk memahami atau mempresentasikan masalah. Bagi saya, memberikan suara seperti tip di restoran: Anda memberi lebih atau kurang dari standar 12% tergantung pada kualitas layanan. Jadi mari kita setuju untuk tidak setuju di sini.
topchef

1
@topchef Saya terlambat 11 tahun untuk ini, tetapi Anda berkata "Sungguh frustasi melihat pertanyaan yang diajukan tanpa persiapan dasar ...". Kemudian bantu memperbaikinya. Jelaskan mengapa Anda tidak memilih. Jika tidak, Anda sama sekali tidak membantu masalah.
tylerr147

Jawaban:


63

Jika saya mengerti dengan benar, tampaknya Anda ingin menjalankan toples dalam proses terpisah dari dalam aplikasi Java GUI Anda.

Untuk melakukan ini, Anda dapat menggunakan:

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

Ini selalu merupakan praktik yang baik untuk menyangga hasil dari proses.


21
Apakah solusi ini portabel?
Pacerier

3
Terima kasih. Saya sudah mencoba exec () func dengan 3 parameter, termasuk parameter "dir" dan tidak berhasil. Dengan hanya satu, kita hanya perlu meletakkan 3 file .jar di tempat yang sama
Duc Tran

Tahukah Anda bagaimana cara mendapatkan Runtimeobjek dari aplikasi java tersebut?
Stommestack

Bisakah kita menggunakan versi yang lebih portabel, menggunakan ProcessBuilder?
Anand Rockzz

Tidak dapat menjalankan program "java": CreateProcess error = 2, Sistem tidak dapat menemukan file yang ditentukan. Mendapatkan kesalahan ini.
Gentleman

27

.jar tidak dapat dieksekusi. Buat instance kelas atau lakukan panggilan ke metode statis apa pun.

EDIT: Tambahkan entri Main-Class saat membuat JAR.

> p.mf (isi p.mf)

Kelas Utama: pk.Test

>Test.java

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

Gunakan kelas Proses dan metodenya,

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

1
Saya pikir idenya adalah bahwa diberi akses ke jar, bagaimana Anda menambahkannya ke classpath untuk memuat kelas darinya.
Jherico

1
Catatan: ini berfungsi hanya karena Anda memiliki java bin di PATH Anda, ini bukan kasus untuk instalasi windows default
poussma

@ AVD: di mana file A.jar harus disimpan?
logan

1
@logan - Di direktori tempat Anda memuat program.
adatapost

Akankah pendekatan ini membuat proses JVM baru atau menggunakan yang sudah ada?
RahulDeep Attri

17

Semoga ini membantu:

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

0

Jika toples ada di classpath Anda, dan Anda tahu class Main-nya, Anda bisa memanggil class utama. Menggunakan DITA-OT sebagai contoh:

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

Perhatikan bahwa ini akan membuat jar bawahan berbagi ruang memori dan jalur kelas dengan jar Anda, dengan semua potensi gangguan yang dapat ditimbulkan. Jika Anda tidak ingin barang itu tercemar, Anda punya pilihan lain, seperti yang disebutkan di atas - yaitu:

  • buat ClassLoader baru dengan toples di dalamnya. Ini lebih aman; Anda setidaknya dapat memisahkan pengetahuan toples baru ke classloader inti jika Anda merancang berbagai hal dengan pengetahuan bahwa Anda akan menggunakan stoples alien. Itulah yang kami lakukan di toko saya untuk sistem plugin kami; aplikasi utama adalah shell kecil dengan pabrik ClassLoader, salinan API, dan pengetahuan bahwa aplikasi sebenarnya adalah plugin pertama yang harus dibuat ClassLoadernya. Plugin adalah sepasang stoples - antarmuka dan implementasi - yang digabungkan menjadi satu. Semua ClassLoader berbagi semua antarmuka, sementara setiap ClassLoader hanya memiliki pengetahuan tentang implementasinya sendiri. Tumpukannya sedikit rumit, tetapi lulus semua pengujian dan bekerja dengan baik.
  • use Runtime.getRuntime.exec(...)(yang sepenuhnya mengisolasi tabung, tetapi memiliki "temukan aplikasi" yang normal, "lepas string Anda dengan benar", "WTF khusus platform", dan "Thread Sistem OMG" dari menjalankan perintah sistem.

0

Yang berikut ini bekerja dengan memulai jar dengan file batch, jika program berjalan sebagai 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);
    }

Di batchfile.bat maka kita dapat mengatakan:

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

-3

Jika Anda java 1.6 maka hal berikut juga bisa dilakukan:

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");
        }
    }
}

4
Saya tidak berpikir ini menjawab pertanyaan OP
Sri Harsha Chilakapati
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.