Hi,
We are trying to integrate jacoco with our faultlocalization tool,
following your usage API example CoreTutorial.java.
Means we initilize a MemoryClassloader in which instrumented classes are
redefined, then load classes from that classloader to execute in order for
jacoco to be able to analyze.
It seems okay when we test a simple program, but for a quite more complicated
one, we get an error about classloader.
This is the stacktrace:
java.lang.LinkageError: loader constraint violation: loader (instance of
sun/misc/Launcher$AppClassLoader)
previously initiated loading for a different type with name
"de/susebox/jtopas/PluginTokenizer"
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
at
java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)
at java.lang.Class.privateGetPublicMethods(Class.java:2547)
at java.lang.Class.privateGetPublicMethods(Class.java:2557)
at java.lang.Class.privateGetPublicMethods(Class.java:2557)
at java.lang.Class.getMethods(Class.java:1410)
at
codecoverage.jacoco.JavaCoCo.extractTestCasesAsRequests(JavaCoCo.java:56)
at codecoverage.jacoco.JavaCoCo.run(JavaCoCo.java:107)
It looks like class "PluginTokenizer" was already loaded (and redefined) by
MemoryClassloader, then by AppClassLoader, that cause violation.
Here are our classes: (I shortened by removing some unrelated lines)
45 public class JavaCoCo implements ICodeCoverage {
46 private Logger<?> logger = Logger.getDefaultLogger();
47 private static final String JUNIT_TEST_METHOD_PREFIX = "test";
48 private static final String JUNIT_TEST_SUITE_PREFIX = "suite";
49 private MemoryClassLoader memoryClassLoader;
50
51 private List<Request> extractTestCasesAsRequests(
52 List<String> junitClassNames) throws
ClassNotFoundException {
53 ArrayList<Request> requests = new ArrayList<Request>();
54 for (String className : junitClassNames) {
55 Class<?> junitClass =
memoryClassLoader.loadClass(className);
56 Method[] methods = junitClass.getMethods();
57 for (Method method : methods) {
58 Test test = method.getAnnotation(Test.class);
59 if (test != null) {
63 Request request =
Request.method(junitClass, method.getName());
64 requests.add(request);
65 }
66 }
67 }
68 return requests;
69 }
70
71 public void run(ICoverageReport report, List<String> testingClassNames,
72 List<String> junitClassNames) throws Exception {
73 report.setTestingClassNames(testingClassNames);
74 List<String> classNameForJaCoco = new
ArrayList<String>(testingClassNames);
75 classNameForJaCoco.addAll(junitClassNames);
76
77 // For instrumentation and runtime we need a IRuntime instance
78 // to collect execution data:
79 final IRuntime runtime = new LoggerRuntime();
80
81 memoryClassLoader = new MemoryClassLoader();
83 // The Instrumenter creates a modified version of our test
target class
84 // that contains additional probes for execution data recording:
85 final Instrumenter instr = new Instrumenter(runtime);
86 ArrayList<byte[]> instrumenteds = new ArrayList<byte[]>();
87
88 for(String clazz: classNameForJaCoco){
89 try {
90
instrumenteds.add(instr.instrument(getTargetClass(clazz), clazz));
91 } catch (IOException e) {
92 logger.logEx(e, "cannot load class " + clazz);
93 throw e;
94 }
95 }
96
97 for(int j = 0; j < classNameForJaCoco.size(); j++){
98 String testingClassName = classNameForJaCoco.get(j);
99 memoryClassLoader.addDefinition(testingClassName,
instrumenteds.get(j));
100 }
101
102 // Now we're ready to run our instrumented class and need to
startup the
103 // runtime first:
104 final RuntimeData data = new RuntimeData();
105 runtime.startup(data);
106
107 List<Request> testcases =
extractTestCasesAsRequests(junitClassNames);
108 for(int i = 0; i < testcases.size(); i++){
109 Request testcase = testcases.get(i);
110
111 data.reset();
112 final Class<?> targetClass =
memoryClassLoader.loadClass(RequestExecution.class.getName());
113
114 // Here we execute our test target class through its
Runnable interface:
115 final Runnable targetInstance = (Runnable)
targetClass.newInstance();
116
117 Method setRequest = targetClass.getMethod("setRequest",
Request.class);
118 setRequest.invoke(targetInstance, testcase);
119
120 targetInstance.run();
121
122 /* Extract the test's running result */
123 Method getResult = targetClass.getMethod("getResult");
124 boolean isPassed = (Boolean)
getResult.invoke(targetInstance);
125 List<Failure> failures =
RequestExecution.getFailureTrace(
126 targetClass, targetInstance);
127 report.addFailureTrace(extractBrkpsFromTrace(failures,
128 testingClassNames));
129
130 // At the end of test execution we collect execution
data and shutdown
131 // the runtime:
132 final ExecutionDataStore executionData = new
ExecutionDataStore();
133 final SessionInfoStore sessionInfos = new
SessionInfoStore();
134 data.collect(executionData, sessionInfos, false);
135
136 // Together with the original class definition we can
calculate coverage
137 // information:
138 final CoverageBuilder coverageBuilder = new
CoverageBuilder();
139 final Analyzer analyzer = new Analyzer(executionData,
coverageBuilder);
140 for(String testingClassName: testingClassNames){
141
analyzer.analyzeClass(getTargetClass(testingClassName), testingClassName);
142 }
143
144 // Let's dump some metrics and line coverage
information:
145 for (final IClassCoverage cc :
coverageBuilder.getClasses()) {
146 // do not display data for junit test file
147
161 }
162 }
163 runtime.shutdown();
164 }
191 }
MemoryClassLoader:
9 public class MemoryClassLoader extends ClassLoader {
10
11 private final Map<String, byte[]> definitions = new HashMap<String,
byte[]>();
12
13 public MemoryClassLoader(ClassLoader parent) {
14 super(parent);
15 }
16
17 public MemoryClassLoader () {
18
19 }
29 public void addDefinition(final String name, final byte[] bytes) {
30 definitions.put(name, bytes);
31 }
32
33 @Override
34 protected Class<?> loadClass(final String name, final boolean resolve)
35 throws ClassNotFoundException {
36 final byte[] bytes = definitions.get(name);
37 if (bytes != null) {
38 Class<?> result = defineClass(name, bytes, 0,
bytes.length);
39 // prevent defining class second time.
40 definitions.remove(name);
41 return result;
42 }
43 return super.loadClass(name, resolve);
44 }
45 }
RequestExecution is a runnable class to execute a junit method as a request.
input of the program:
testingClassNames:
"de.susebox.java.io.ExtIOException",
"de.susebox.java.lang.ExtIndexOutOfBoundsException",
"de.susebox.java.util.InputStreamTokenizer",
"de.susebox.jtopas.PluginTokenizer"
junitClassNames:
"de.susebox.java.util.TestTokenizerProperties",
"de.susebox.java.util.TestTokenProperties",
"de.susebox.java.util.TestInputStreamTokenizer",
"de.susebox.java.util.TestDifficultSituations",
"de.susebox.jtopas.TestPluginTokenizer",
"de.susebox.jtopas.TestTokenizerSpeed"
In this test, PluginTokenizer is called in both TestPluginTokenizer, and
TestTokenizerSpeed
Do you have any idea about the problem and how to fix it?
Let me know if you need any more information.
Thanks in advance for the help,
lyly
--
You received this message because you are subscribed to the Google Groups
"JaCoCo and EclEmma Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.