ThiporKong
(Thipor Kong)
March 18, 2016, 12:36pm
1
JavaExec doesn’t work for long classpaths on Windows. The problem is similar to the ones described here or here .
The underlying reason is, that the JavaExecHandleBuilder (from which DefaultJavaExecAction derives) just puts the whole classpath into the ‘-cp’ command line parameter for the JVM.
Are there any plans for supporting long classpaths properly out-of-the-box?
If not, what’s the proper approach to configure the use of your own JavaExecAction implementation?
I have seen there are ExecActionFactory.newJavaExecAction() and ProjectScopeServices.createExecActionFactory() , but couldn’t figure out how to plug in my own factories.
1 Like
Feel free to make use of this specialization of DefaultJavaExecAction:
public class LongClasspathExecAction extends DefaultJavaExecAction {
public LongClasspathExecAction(final FileResolver fileResolver) {
super(fileResolver);
}
@Override
public List<String> getAllJvmArgs() {
final List<String> allArgs = new ArrayList<>(getJvmArgs());
final FileCollection classpath = getClasspath();
if (!classpath.isEmpty()) {
try {
final File jarFile = toJarWithClasspath(classpath.getFiles());
allArgs.add("-cp");
allArgs.add(jarFile.toString());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
return allArgs;
}
private static final String MATCH_CHUNKS_OF_70_CHARACTERS = "(?<=\\G.{70})";
private static File toJarWithClasspath(final Set<File> files) throws IOException {
final File jarFile = File.createTempFile("long-classpath", ".jar");
try (final ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(jarFile))) {
zip.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
try (final PrintWriter pw = new PrintWriter(new OutputStreamWriter(zip, StandardCharsets.UTF_8))) {
pw.println("Manifest-Version: 1.0");
final String classPath = CollectionUtils.join(" ", CollectionUtils.collect(files, File::toURI));
final String classPathEntry = "Class-Path: " + classPath;
pw.println(CollectionUtils.join("\n ", classPathEntry.split(MATCH_CHUNKS_OF_70_CHARACTERS)));
}
}
return jarFile;
}
}
1 Like
How do we make use of this? I can hack something together by with project.javaExec()
, but is there a way to swap the default implementation with this one?
Btw, for how many posts there are about this, it’s crazy there’s no warning or real fix in gradle core yet.
4 Likes