Thực thi một jar khác trong chương trình Java


114

Tôi đã viết một số ứng dụng java đơn giản có tên là A.jar, B.jar.

Bây giờ tôi muốn viết một chương trình java GUI để người dùng có thể nhấn nút A để thực thi A.jar và nút B để thực thi B.jar.

Ngoài ra, tôi muốn xuất chi tiết quy trình thời gian chạy trong chương trình GUI của mình.

Bất kì lời đề nghị nào?


31
Không chắc tại sao điều này lại bị bỏ phiếu. Giải thích cho anh ấy hiểu tại sao những giả định của anh ấy có thể sai, nhưng đừng từ chối câu hỏi.
William Brendel

-1 thuật ngữ Java cơ bản không được sử dụng chính xác và câu hỏi rất mơ hồ và để lại rất nhiều cho việc phỏng đoán thứ hai. Cân nhắc diễn đạt lại câu hỏi của bạn với nhiều chi tiết hơn hoặc chỉ cần đọc về Java classpath và những điều cơ bản khác trước tiên.
topchef

21
@grigory: Thấy chưa, đó là điều bạn nên hỏi ngay từ đầu, thay vì từ chối ngay lập tức. Downvoting mà không hề hỏi để biết thêm không làm bất kỳ tốt ...
William Brendel

4
@William, xin lỗi vì đã nhấn nút muộn hơn bạn vài giây. Tôi bảo lưu quyền biểu quyết của mình với bình luận tiếp theo. Thật khó chịu khi thấy những câu hỏi được đặt ra mà không có sự chuẩn bị cơ bản và / hoặc nỗ lực để hiểu hoặc trình bày vấn đề. Đối với tôi, việc bỏ phiếu giống như một khoản tiền boa tại một nhà hàng: bạn cho nhiều hơn hoặc ít hơn tiêu chuẩn 12% tùy thuộc vào chất lượng dịch vụ. Vì vậy, chúng ta hãy đồng ý không đồng ý ở đây.
topchef

1
@topchef Tôi đến muộn 11 năm, nhưng bạn nói "Thật bực bội khi thấy những câu hỏi được hỏi mà không có sự chuẩn bị cơ bản ...". Sau đó, giúp sửa chữa nó. Giải thích lý do tại sao bạn phản đối. Nếu không thì bạn không giúp được gì cho vấn đề cả.
tylerr147

Câu trả lời:


63

Nếu tôi hiểu chính xác, có vẻ như bạn muốn chạy các bình trong một quy trình riêng biệt từ bên trong ứng dụng java GUI của mình.

Để làm điều này, bạn có thể sử dụng:

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

Nó luôn luôn thực hành tốt để đệm đầu ra của quá trình.


21
Giải pháp này có di động không?
Pacerier

3
cảm ơn. Tôi đã thử thực hiện () func với 3 tham số, bao gồm cả tham số "dir" và nó không hoạt động. Với chỉ một, chúng ta chỉ cần đặt 3 file .jar trong cùng một vị trí
Đức Trần

Bạn có biết cách lấy Runtimeđối tượng của ứng dụng java đó không?
stommestack

Chúng ta có thể sử dụng phiên bản di động hơn, sử dụng ProcessBuilder không?
Anand Rockzz

Không thể chạy chương trình "java": Lỗi CreateProcess = 2, Hệ thống không thể tìm thấy tệp được chỉ định. Gặp lỗi này.
Gentleman

27

.jar không thực thi được. Khởi tạo các lớp hoặc thực hiện cuộc gọi đến bất kỳ phương thức tĩnh nào.

CHỈNH SỬA: Thêm mục nhập Lớp chính trong khi tạo JAR.

> p.mf (nội dung của p.mf)

Lớp chính: pk.Test

>Test.java

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

Sử dụng lớp Process và các phương thức của nó,

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
Tôi nghĩ ý tưởng là được cấp quyền truy cập vào một jar, làm thế nào để bạn thêm nó vào classpath để tải các lớp từ nó.
Jherico

1
Lưu ý: nó hoạt động chỉ vì bạn có bin java trong PATH của bạn, đây không phải là trường hợp cho các cửa sổ mặc định cài đặt
poussma

@AVD: tệp A.jar nên được giữ ở đâu?
logan

1
@logan - Trong thư mục mà bạn đang tải một chương trình.
adatapost

Cách tiếp cận này sẽ tạo ra một quy trình JVM mới hay sử dụng quy trình hiện có?
RahulDeep Attri

17

Hi vọng điêu nay co ich:

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

Nếu jar nằm trong classpath của bạn và bạn biết lớp Chính của nó, bạn chỉ có thể gọi lớp chính. Sử dụng DITA-OT làm ví dụ:

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

Lưu ý rằng điều này sẽ làm cho jar cấp dưới chia sẻ không gian bộ nhớ và một classpath với jar của bạn, với tất cả khả năng gây nhiễu có thể gây ra. Nếu bạn không muốn thứ đó bị ô nhiễm, bạn có các lựa chọn khác, như đã đề cập ở trên - cụ thể là:

  • tạo một ClassLoader mới với jar trong đó. Điều này là an toàn hơn; ít nhất bạn có thể tách kiến ​​thức của jar mới với một trình tải lớp cốt lõi nếu bạn kiến ​​trúc mọi thứ với kiến ​​thức rằng bạn sẽ sử dụng các lọ ngoài hành tinh. Đó là những gì chúng tôi làm trong cửa hàng của tôi cho hệ thống plugin của chúng tôi; ứng dụng chính là một trình bao nhỏ với nhà máy ClassLoader, một bản sao của API và biết rằng ứng dụng thực là plugin đầu tiên mà nó nên xây dựng ClassLoader. Các plugin là một cặp - giao diện và triển khai - được nén lại với nhau. Tất cả các ClassLoader đều chia sẻ tất cả các giao diện, trong khi mỗi ClassLoader chỉ có kiến ​​thức về cách triển khai của riêng nó. Ngăn xếp hơi phức tạp một chút, nhưng nó vượt qua tất cả các bài kiểm tra và hoạt động tuyệt vời.
  • sử dụng Runtime.getRuntime.exec(...)(cách ly hoàn toàn jar, nhưng có các cạm bẫy thông thường "tìm ứng dụng", "thoát đúng chuỗi của bạn", "WTF dành riêng cho nền tảng" và "Chuỗi hệ thống OMG" khi chạy các lệnh hệ thống.

0

Các thao tác sau đây hoạt động bằng cách khởi động jar với một tệp loạt, trong trường hợp chương trình chạy riêng lẻ:

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

Trong batchfile.bat, chúng ta có thể nói:

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

-3

Nếu bạn là java 1.6 thì những điều sau cũng có thể được thực hiện:

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
Tôi không nghĩ rằng câu trả lời này câu hỏi của OP
Sri Harsha Chilakapati
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.