我想从当前的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。还有其他解决方法吗?
答案 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应用程序的另一个解决方案是使用类加载器。这具有以下优点:
要使用此解决方案,只需使用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"});