如何在运行时在java中设置多个类路径条目?

时间:2016-09-08 06:51:48

标签: java runtime classpath

我想从当前的java项目中执行一个java程序。它有多个jar依赖项,应该在执行它们之前在类路径中添加。首先,我尝试使用普通的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命令之前动态设置classpath:

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

但它没有按预期设置classpath。还有其他解决方法吗?

3 个答案:

答案 0 :(得分:3)

除了@Szmeby的答案,如果你不知道如何在里面使用类路径的文件,你可以尝试创建一个&#34;路径jar&#34;。

&#34; Pathing jar&#34;仅包含Manifest.mf文件,其中包含下一个条目:

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

您还可以使用通配符来缩短长度。

答案 1 :(得分:1)

我认为这主要是由命令行长度限制引起的操作系统问题,而不是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命令提示符中内联文件内容。好吧,至少我希望它能给你一些继续前进的想法。

答案 2 :(得分:1)

从Java启动Java应用程序的另一个解决方案是使用类加载器。这具有以下优点:

  • 您可以保证新程序使用与您的程序相同的Java版本运行,从而使多个安装成为无问题。
  • 如果您愿意,新程序可以更轻松地与您的程序进行通信(尽管如果您选择此路线,则根本不需要这样做。)
  • 它更独立于平台,因为任何具有奇怪命令行配置的设置都不是问题。

要使用此解决方案,只需使用URLClassLoader加载所有必需的jar,然后通过反射调用main方法:

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