Instr fails to add instrumenation arguments to classpath for Java 11 causing instrumentation failures
Clemens Ballarin
clemens.ballarin at ankordata.de
Fri Oct 9 09:48:10 UTC 2020
Static instrumentation is done as follows:
java -jar jcov.jar instr -verbose -t <template> -i <pattern> -o
<output> <input1> <input2> ...
While this works for Java 8, with Java 11 I get error messages like this:
[ERROR] Failed to read class: gnu/trove/map/hash/TIntLongHashMap.
Reason: Can't read class gnu/trove/map/hash/TIntLongHashMap from
classloader jdk.internal.loader.ClassLoaders$AppClassLoader at 55054057
[ERROR] SCHWERWIEGEND: Error instrumenting archive entry 'xxx.class'
in 'yyy.jar' - skipped
[ERROR] Exception details: Can't read superclass bytecode. Please add it
to the classpath.
It looks like for Java 8 all inputs are added to the system classpath
via com.sun.tdk.jcov.Utils.addToClasspath(String[]):
public static void addToClasspath(String[] path) {
if (ClassLoader.getSystemClassLoader() instanceof URLClassLoader) {
URLClassLoader sysloader = (URLClassLoader)
ClassLoader.getSystemClassLoader();
Class sysclass = URLClassLoader.class;
try {
Method method = sysclass.getDeclaredMethod("addURL",
new Class[]{URL.class});
method.setAccessible(true);
URL[] urls = new URL[path.length];
for (int i = 0; i < path.length; i++) {
urls[i] = new File(path[i]).toURI().toURL();
method.invoke(sysloader, new Object[]{urls[i]});
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
But this doesn't work for Java 11 since
jdk.internal.loader.ClassLoaders.AppClassLoader is not an instance of
URLClassLoader. (jcov commit 4fd8b8e)
Is there a recommended workaround?
Clemens
More information about the jcov-dev
mailing list