2012-03-03 22 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に与えるほうが良いでしょう。

Runtimeの代わりにProcessBuilderを使用してください。

2

foo.jarを直接実行できますか?それは主な方法を持つマニフェストを持っていますか?

私はあなたができると推測しています。したがって、foo.Mainのようなクラスの中でmainメソッドを起動したいとします。

オプション1:クラスパスにfoo.jarを含めます。 IDEを使用している場合は、foo.jarをライブラリとして追加するだけです。今すぐパッケージをインポートして(パッケージfooを呼び出せるように)、Javaコードの1行から2番目のJavaプログラムを起動することができます。 foo.Main.main(null); ほとんどの場合、あなたが別のスレッドでこれをしたいと思う:

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

、その後、あなたはこれで起動します:

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

オプション2 あなたはfooパッケージ内のクラスをロードすることができます実行時にクラスローダーを使用して たjava.lang.ClassLoaderのJavadocを参照してくださいthis example of a CustomClassLoader

関連する問題