รัน jar อื่นในโปรแกรม Java


115

ฉันได้เขียนแอปพลิเคชั่น java ง่ายๆหลายตัวชื่อ A.jar, B.jar

ตอนนี้ฉันต้องการเขียนโปรแกรม GUI java เพื่อให้ผู้ใช้สามารถกดปุ่ม A เพื่อเรียกใช้งาน A. jar และปุ่ม B เพื่อเรียกใช้งาน B.jar

นอกจากนี้ฉันต้องการส่งออกรายละเอียดกระบวนการรันไทม์ในโปรแกรม GUI ของฉัน

ข้อเสนอแนะใด ๆ ?


31
ไม่แน่ใจว่าเหตุใดจึงโหวตลง อธิบายให้เขาเข้าใจว่าเหตุใดสมมติฐานของเขาอาจผิด แต่อย่าลงคะแนนคำถาม
William Brendel

-1 คำศัพท์พื้นฐานของ Java ไม่ได้ใช้อย่างถูกต้องและคำถามคลุมเครือมากและทิ้งไว้มากสำหรับการเดาครั้งที่สอง พิจารณาการเรียบเรียงคำถามของคุณใหม่พร้อมรายละเอียดเพิ่มเติมหรืออ่านเกี่ยวกับ Java classpath และพื้นฐานอื่น ๆ ก่อน
topchef

21
@grigory: ดูนั่นคือสิ่งที่คุณควรถามตั้งแต่แรกแทนที่จะลงคะแนนทันที การลงคะแนนโดยไม่ขอข้อมูลเพิ่มเติมไม่ได้ส่งผลดีใด ๆ ...
William Brendel

4
@ วิลเลียมขอโทษที่กดปุ่มช้ากว่าที่คุณทำไม่กี่วินาที ฉันขอสงวนสิทธิ์ในการโหวตพร้อมกับความคิดเห็นที่ตามมา เป็นเรื่องน่าผิดหวังที่เห็นคำถามที่ถามโดยไม่มีการเตรียมการพื้นฐานและ / หรือความพยายามในการทำความเข้าใจหรือนำเสนอปัญหา การโหวตเป็นเหมือนทิปที่ร้านอาหารสำหรับฉัน: คุณให้มากกว่าหรือน้อยกว่ามาตรฐาน 12% ขึ้นอยู่กับคุณภาพการบริการ มาเห็นด้วยกับไม่เห็นด้วยตรงนี้
topchef

1
@topchef ฉันช้าไป 11 ปีแล้ว แต่คุณบอกว่า "มันน่าผิดหวังที่เห็นคำถามที่ถามโดยไม่มีการเตรียมการพื้นฐาน ... " แล้วช่วยแก้ไข. อธิบายว่าทำไมคุณจึงลดคะแนน มิฉะนั้นคุณจะไม่ได้ช่วยแก้ปัญหาเลย
tylerr147

คำตอบ:


63

ถ้าฉันเข้าใจถูกต้องดูเหมือนว่าคุณต้องการเรียกใช้ jars ในกระบวนการแยกต่างหากจากภายในแอปพลิเคชัน java GUI ของคุณ

ในการดำเนินการนี้คุณสามารถใช้:

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

แนวทางปฏิบัติที่ดีเสมอในการบัฟเฟอร์ผลลัพธ์ของกระบวนการ


21
โซลูชันนี้พกพาได้หรือไม่?
Pacerier

3
ขอบคุณ ฉันได้ลอง exec () func ที่มีพารามิเตอร์ 3 ตัวซึ่งรวมถึงพารามิเตอร์ "dir" แต่ไม่ได้ผล เพียงไฟล์เดียวเราต้องใส่ไฟล์. jar ทั้ง 3 ไฟล์ไว้ที่เดียวกัน
Duc Tran

คุณรู้วิธีรับRuntimeวัตถุของแอปพลิเคชัน java หรือไม่?
stommestack

เราสามารถใช้เวอร์ชันพกพามากขึ้นโดยใช้ ProcessBuilder ได้หรือไม่?
Anand Rockzz

ไม่สามารถรันโปรแกรม "java": CreateProcess error = 2 ระบบไม่พบไฟล์ที่ระบุ รับข้อผิดพลาดนี้
สุภาพบุรุษ

27

.jar ไม่สามารถใช้งานได้ สร้างอินสแตนซ์คลาสหรือโทรไปยังเมธอดคงที่

แก้ไข: เพิ่มรายการระดับหลักในขณะที่สร้าง 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");
  }
}

ใช้คลาสกระบวนการและเป็นวิธีการ

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
ฉันคิดว่าแนวคิดคือเมื่อได้รับการเข้าถึง jar คุณจะเพิ่มลงใน classpath ได้อย่างไรเพื่อโหลดคลาสออกจากมัน
Jherico

1
หมายเหตุ: ใช้งานได้เฉพาะเนื่องจากคุณมี java bin ใน PATH ของคุณนี่ไม่ใช่กรณีสำหรับการติดตั้ง windows เริ่มต้น
poussma

@AVD: ไฟล์ A.jar ควรเก็บไว้ที่ไหน?
โลแกน

1
@logan - ในไดเร็กทอรีที่คุณกำลังโหลดโปรแกรม
adatapost

วิธีนี้จะสร้างกระบวนการ JVM ใหม่หรือใช้กระบวนการที่มีอยู่?
RahulDeep Attri

17

หวังว่านี่จะช่วยได้:

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

ถ้า jar อยู่ใน classpath ของคุณและคุณรู้จัก Main class คุณก็สามารถเรียกใช้ main class ได้ ใช้ DITA-OT เป็นตัวอย่าง:

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

โปรดทราบว่านี่จะทำให้ jar รองแบ่งใช้พื้นที่หน่วยความจำและ classpath กับ jar ของคุณโดยมีโอกาสเกิดสัญญาณรบกวนทั้งหมดที่อาจทำให้เกิด หากคุณไม่ต้องการให้สิ่งนั้นปนเปื้อนคุณมีทางเลือกอื่นดังที่กล่าวไว้ข้างต้นนั่นคือ:

  • สร้าง ClassLoader ใหม่โดยมีโถอยู่ในนั้น ปลอดภัยกว่า อย่างน้อยคุณสามารถแยกความรู้ของ jar ใหม่ไปยัง core classloader ได้หากคุณออกแบบสิ่งต่าง ๆ ด้วยความรู้ที่คุณจะใช้ประโยชน์จากไหต่างดาว เป็นสิ่งที่เราทำในร้านของฉันสำหรับระบบปลั๊กอินของเรา แอปพลิเคชันหลักคือเชลล์ขนาดเล็กที่มีโรงงาน ClassLoader สำเนาของ API และทราบว่าแอปพลิเคชันจริงเป็นปลั๊กอินตัวแรกที่ควรสร้าง ClassLoader ปลั๊กอินเป็นส่วนต่อประสานและการใช้งานที่รวมเข้าด้วยกัน ClassLoaders ทั้งหมดแชร์อินเทอร์เฟซทั้งหมดในขณะที่ ClassLoader แต่ละตัวมีความรู้เกี่ยวกับการนำไปใช้งานของตัวเองเท่านั้น สแต็กมีความซับซ้อนเล็กน้อย แต่ผ่านการทดสอบทั้งหมดและทำงานได้อย่างสวยงาม
  • ใช้Runtime.getRuntime.exec(...)(ซึ่งแยก jar ทั้งหมด แต่มีข้อผิดพลาด "find the application", "escape your strings right", "platform-specific WTF" และ "OMG System Threads"

0

ต่อไปนี้ทำงานโดยเริ่มต้น 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

-3

หากคุณเป็น 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");
        }
    }
}

4
ฉันไม่คิดว่าจะตอบคำถามของ OP
Sri Harsha Chilakapati
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.