2012-03-03 116 views

回答

3

最簡單的解決方案(as Thorn pointed out)將有罐子作爲構建時依賴,並從你的代碼中靜態調用它:

ExternalJarMainClass.main(new String[]{"arguments", "to", "main"}); 

但如果這不可行,您可以使用URLClassLoader來動態加載jar。如果jar確實可以運行,那麼你可以從META-INF/MANIFEST.MF讀取主類並通過反射調用main

這是與創建單獨進程不同的方法,因爲外部代碼將在與應用程序相同的進程中運行。也許這是可取的,也許不是 - 取決於情況。

下面是一個(匆忙書寫和有缺陷的)樣本助手類,就是這樣做的。

import java.io.BufferedReader; 
import java.io.File; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.lang.reflect.InvocationTargetException; 
import java.lang.reflect.Method; 
import java.net.URL; 
import java.net.URLClassLoader; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

public class JarRunner { 

    private final Method entryPoint; 

    public JarRunner(File jarFile) throws 
      ClassNotFoundException, 
      IOException, 
      NoSuchMethodException { 
     URL jarUrl = jarFile.toURI().toURL(); 
     URLClassLoader loader = URLClassLoader.newInstance(
       new URL[]{jarUrl}); 
     URL manifestUrl = loader.findResource("META-INF/MANIFEST.MF"); 
     String manifest = resourceToString(manifestUrl); 
     Class<?> clazz = loader.loadClass(findMainClassName(manifest)); 
     entryPoint = clazz.getMethod("main", String[].class); 
    } 

    public void run(String[] argsToMain) throws 
      IllegalAccessException, 
      IllegalArgumentException, 
      InvocationTargetException { 
     entryPoint.invoke(null, (Object) argsToMain); 
    } 

    private static String resourceToString(URL url) throws IOException { 
     InputStream contentStream = url.openStream(); 
     try { 
      BufferedReader r = new BufferedReader(
        new InputStreamReader(contentStream)); 
      StringBuilder sb = new StringBuilder(); 
      String line = null; 
      do { 
       line = r.readLine(); 
       if (line != null) { 
        sb.append(line).append('\n'); 
       } 
      } while (line != null); 
      return sb.toString(); 
     } finally { 
      contentStream.close(); 
     } 
    } 

    private static String findMainClassName(String manifest) { 
     Matcher m = MAIN_CLASS_PATTERN.matcher(manifest); 
     if (m.find()) { 
      return m.group(1); 
     } 
     return null; 
    } 

    private static final Pattern MAIN_CLASS_PATTERN = 
      Pattern.compile("Main-Class: (.+)"); 
} 

使用範例:

JarRunner jr = new JarRunner(new File("path/to/MyJar.jar")); 
jr.run(new String[]{"arg1", "arg2"}); 
1

檢查java -jar foo.jar從命令行運行正確。還要確保java在路徑中。在參數中提供到java.exe的絕對路徑可能會更好。請使用ProcessBuilder代替Runtime

2

你可以直接運行foo.jar嗎?它有一個主要方法的清單嗎?

我猜你可以。所以你想要啓動一個類的主要方法,如foo.Main

選項1:在類路徑中包含foo.jar。如果您使用的是IDE,那麼這意味着將foo.jar添加爲庫。現在您可以自由導入包(可以調用包foo)並從一行Java代碼啓動第二個Java程序: foo.Main.main(null); 最有可能你會想這樣做在一個單獨的線程:

class FooRunner extends Thread { 
    public void run() { 
     foo.Main.main(null); 
    } 
} 

,然後你將與此推出:

FooRunner secondaryApp = new FooRunner(); 
secondaryApp.start(); 

選項2 您可以在富包加載類在運行時使用類加載器。 見的Javadoc的java.lang.ClassLoader和this example of a CustomClassLoader