從 Java 程式執行 JAR 文件
1. 簡介
在處理 Java 專案時,我們可能會遇到這樣的情況:我們需要在 Java 程式內部以單獨的進程執行外部 JAR(可執行 JAR)並查看輸出,或者我們可能想要在外部 JAR 中使用main
方法執行類別檔案。
在本教程中,我們將了解如何處理這兩個場景和程式碼範例。
2. 執行可執行 JAR
可執行 JAR 是一種包含具有Main-Class
屬性集的清單檔案的 JAR 檔案。該屬性指向應該首先運行的類別文件(使用main
方法)。
我們可以使用java -jar <example.jar>
命令從命令列運行這個 JAR。我們可以使用ProcessBuilder
從 Java 程式獲得類似的結果。
下面的程式碼示範如何以程式設計方式將可執行 JAR 作為單獨的進程運行並在控制台中查看輸出:
@Test
public void givenRunnableJar_whenExecuted_thenShouldRunSuccessfully() {
Process process = null;
try {
String jarFile = new File(Objects.requireNonNull(getClass().getClassLoader()
.getResource(RUNNABLE_JAR_PATH))
.toURI()).getAbsolutePath();
ProcessBuilder processBuilder = new ProcessBuilder("java", "-jar", jarFile);
processBuilder.redirectErrorStream(true);
process = processBuilder.start();
try (InputStream inputStream = process.getInputStream()) {
byte[] output = inputStream.readAllBytes();
System.out.println("Output: " + new String(output));
}
int exitCode = process.waitFor();
Assert.assertEquals("Process exited with an unexpected exit code", 0, exitCode);
} catch (IOException | InterruptedException | URISyntaxException e) {
Assert.fail("Test failed due to exception: " + e.getMessage());
} finally {
if (process != null) {
process.destroy();
}
}
}
此測試檢查可執行 JAR 是否成功執行。
最初,我們透過提供 JAR 檔案(在本例中為可執行 JAR)的絕對路徑來建立一個File
物件。 getClass().getClassLoader().getResource(RUNNABLE_JAR_PATH)
方法取得資源 URL,我們確保它不null
並將其轉換為 URI。
然後,我們使用java -jar
設定命令,這是執行可執行 JAR 的標準方法。接下來,我們使用ProcessBuilder
將 JAR 作為新進程執行。
一旦開始執行,我們就會嘗試從輸入流中捕獲程式輸出。然後將輸出轉換為字串並列印在控制台上。它與我們執行 java – jar
命令時看到的內容類似。
之後,我們使用process.waitFor()
等待流程完成。如果退出代碼為零,則表示執行成功。如果退出程式碼是非零值,則表示執行期間發生錯誤,測試失敗。
3.執行不可執行的 JAR 文件
不可執行 JAR 檔案在其清單檔案中沒有Main-Class
屬性。我們必須明確提及具有主要方法的類別。
下面的程式碼示範如何以程式設計方式將不可執行 JAR 中的類別檔案作為單獨的進程執行,並在控制台中查看輸出:
@Test
public void givenNonRunnableJar_whenExecutedWithMainClass_thenShouldRunSuccessfully() {
Process process = null;
try {
String jarFile = new File(Objects.requireNonNull(getClass().getClassLoader()
.getResource(NON_RUNNABLE_JAR_PATH))
.toURI()).getAbsolutePath();
String[] command = { "java", "-cp", jarFile, "com.company.HelloWorld", "arg1", "arg2" };
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.redirectErrorStream(true);
process = processBuilder.start(); // Start process
try (InputStream inputStream = process.getInputStream()) {
byte[] output = inputStream.readAllBytes();
System.out.println("Output: " + new String(output));
}
int exitCode = process.waitFor();
Assert.assertEquals("Process exited with an unexpected exit code", 0, exitCode);
} catch (IOException | InterruptedException | URISyntaxException e) {
Assert.fail("Test failed due to exception: " + e.getMessage());
} finally {
if (process != null) {
process.destroy(); // Ensure cleanup in all Java versions
}
}
}
上述測試檢查我們是否可以執行不可運行 jar 中的主類別。
一開始,我們透過提供 JAR 檔案(在本例中為不可執行 JAR)的絕對路徑來建立a process.waitFor
物件。
然後我們使用ProcessBuilder
來設定執行環境。 redirectErrorStream(true)
方法將錯誤流與標準輸出流合併,以便我們可以在一個地方捕獲所有輸出。
然後使用processBuilder.start()
該指令作為新程序執行。我們從進程的輸入流中捕獲程式的輸出,然後將其轉換為字串以列印在控制台上。輸出與我們手動運行命令時看到的輸出類似。
最後,使用process.waitFor(),
我們監視該過程直到它完成。
如果退出代碼為零,則表示 JAR 執行成功,如果退出代碼為非零值,則表示執行 JAR 時發生錯誤。
4. 結論
在本文中,我們了解如何簡單地從 Java 程式執行 JAR 檔案。雖然我們不需要明確提及運行可執行 JAR 的類,但對於不可執行 JAR,我們必須這樣做。
我們也了解如何使用ProcessBuilder
類別進行正確的流處理並將 jar 作為單獨的進程執行。
和往常一樣,範例的原始程式碼可以在 GitHub 上找到。