2016-09-08 10 views
2

現在のJavaプロジェクトから1つのJavaプログラムを実行します。複数のjar依存関係があり、実行前にクラスパスに追加する必要があります。まず私は、通常のjavaコマンドを使用して実行してみました -実行時にjavaで複数のクラスパスエントリを設定するには?

String classDir = ""; 
    for (int i = 0; i < compilerConfiguration.getClasspathEntries().size(); i++) { 
     classDir = classDir + compilerConfiguration.getClasspathEntries().get(i) + ";"; 
    } 
    runProcess("java -cp " + classDir + " topLevelProject.com.test.project.App"); 

    private static void runProcess(String command) throws Exception { 
    Process pro = Runtime.getRuntime().exec(command); 
    printLines(command + " stdout:", pro.getInputStream()); 
    printLines(command + " stderr:", pro.getErrorStream()); 
    pro.waitFor(); 
    System.out.println(command + " exitValue() " + pro.exitValue()); 
    } 

しかし、複数のクラスパスのエントリがあるとして、それは私にエラーを与える -

java.io.IOException: Cannot run program "java": CreateProcess error=206, The filename or extension is too long 

classDirの内容は多少このようなものです -

E:\test\maven\com.test.project\target\classes;C:\Users\dd\.m2\repository\p2\osgi\bundle\com.t.cep.studio.cli\5.3.0.164\com.t.cep.studio.cli-5.3.0.164.jar[+com/t/cep/studio/cli/studiotools/*;?**/*];C:\Users\dd\.m2\repository\p2\osgi\bundle\org.eclipse.core.runtime\3.11.1.v20150903-1804\org.eclipse.core.runtime-3.11.1.v20150903-1804.jar[~org/eclipse/core/internal/preferences/legacy/*;~org/eclipse/core/internal/runtime/*;+org/eclipse/core/runtime/*;?**/*]; 

あるいは、javaコマンドを実行する前にクラスパスを動的に設定しようとしました。

try { 
     for (int i = 0; i < compilerConfiguration.getClasspathEntries().size(); i++) { 
      String filePath = "file://" + compilerConfiguration.getClasspathEntries().get(i); 
      URL[] url = { new URL(filePath) }; 
      ClassLoader currentThreadClassLoader = Thread.currentThread().getContextClassLoader(); 
      URLClassLoader urlClassLoader = new URLClassLoader(url, currentThreadClassLoader); 
      Thread.currentThread().setContextClassLoader(urlClassLoader); 
     } 
     runProcess("java topLevelProject.com.test.project.App"); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

しかし、期待通りにクラスパスを設定していません。その他の回避策?

+0

あなたの第二の方法は、実際にどこにでもクラスパスを設定していません。最初のものについては、ファイルへのパスに空白が含まれていますか? – RealSkeptic

+0

はありません。スペースはありません。 'compilerConfiguration.getClasspathEntries()'には141個のエントリがあります。私は2番目の方法で何かを逃していますか? – Disha

+0

ええ、コマンドが別のJVMで実行されているため、現在のスレッドのクラスローダーとは関係がないという事実がなくなっています。 '-cp'(または' CLASSPATH'環境変数)を渡す必要があります。あなたは何とか 'classDir'で正確な文字列を共有できますか? – RealSkeptic

答えて

3

@Szmeby答えに加えて、classpathの内部でファイルを使用する方法がわからない場合は、 "pathing jar"を作成してみてください。

Class-Path: some.jar another.jar others.jar 

あなたはまた、長さを短くするためにワイルドカードを使用することができます。

は、「パス・瓶は、」次のエントリを含んでいるだけでManifest.mfファイルが含まれています。

1

私はそれが主にコマンドラインの長さの制限によって引き起こされるOSの問題ではなく、Javaの問題だと思う。私はjdepsで遊んでいたときも同じ問題を抱えていました。巨大なクラスパスも必要でした。最終的には、クラスパスをプレーンテキストファイルにエクスポートし、そのファイルコンテンツをコマンド引数としてインライン展開しました。

クラスパス文字列を含むテキストファイルの名前があると仮定:cp.txt

その内容(一部):

/home/anon/.m2/repository/com/app/generator/2.0.jar:/home/anon/.m2/repository/com/app/model/2.0.jar:/home/anon/.m2/repository/com/generator-helpers/2.0.jar:/home/anon/.m2/repository/org/eclipse/emf/org.eclipse.emf.ecore/2.10.1-v20140901-1043/org.eclipse.emf.ecore-2.10.1-v20140901-1043.jar:/home/anon/.m2/repository/org/eclipse/emf/org.eclipse.emf.common/2.10.1-v20140901-1043/org.eclipse.emf.common-2.10.1-v20140901-1043.jar:/home/anon/.m2/repository/org/eclipse/emf/org.eclipse.emf.ecore.xmi/2.10.1-v20140901-1043/org.eclipse.emf.ecore.xmi-2.10.1-v20140901-1043.jar:/home/anon/.m2/repository/commons-io/commons-io/2.1/commons-io-2.1.jar:etc... 

その後、あなたは、このようなあなたのコマンドを実行する必要があります。

runProcess("java -cp $(< cp.txt) topLevelProject.com.test.project.App"); 

任意のサイズのクラスパス文字列を使用できますが、Linux専用ソリューションです。 Windowsのコマンドプロンプトでファイルコンテンツをインライン化する方法がわかりません。まあ、少なくとも私はそれがあなたに移動するためのいくつかのアイデアを与えることを願っています。

+0

ありがとうございました。プラットフォーム固有のものだったので、私は自分のプロジェクトにパスジャーを使った – Disha

1

JavaアプリケーションをJavaから起動するもう1つの方法は、クラスローダーを使用することです。これには次の利点があります。

  • 新しいプログラムはプログラムと同じJavaバージョンで実行されるため、複数のインストールが問題になりません。
  • 新しいプログラムは、必要に応じてプログラムとの通信をより簡単に行うことができます(ただし、このルートを選択してもこれは必要ありません)。
  • 奇妙なコマンドライン構成のセットアップが問題ではないという点で、プラットフォームがより独立しています。

単にURLClassLoaderのと必要なjarファイルのすべてをロードし、その後、リフレクションを介してメインメソッドを呼び出して、このソリューションを使用するには:

URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{ 
    new URL("file://path/to/jar/1.jar"), 
    new URL("file://path/to/jar/2.jar"), 
    new URL("file://path/to/jar/3.jar"), 
    new URL("file://path/to/jar/4.jar"), 
    new URL("file://path/to/jar/5.jar") 
}); 

Class<?> clazz = urlClassLoader.loadClass("topLevelProject.com.test.project.App"); 
clazz.getMethod("main", String[].class).invoke(null, new String[]{"Command", "Line", "Arguments", "Here"}); 
関連する問題