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