【发布时间】:2018-03-12 02:33:11
【问题描述】:
我按照http://www.jacoco.org/jacoco/trunk/doc/examples/java/CoreTutorial.java 的 CoreTutorial 示例课程了解如何将 Jacoco 合并到项目中。
但是,我遇到了与所使用的 MemoryClassLoader 类相关的 java.lang.LinkageError 问题。
/**
* A class loader that loads classes from in-memory data.
*/
public static class MemoryClassLoader extends ClassLoader {
private final Map<String, byte[]> definitions = new HashMap<String, byte[]>();
/**
* Add a in-memory representation of a class.
*
* @param name
* name of the class
* @param bytes
* class definition
*/
public void addDefinition(final String name, final byte[] bytes) {
definitions.put(name, bytes);
}
@Override
protected Class<?> loadClass(final String name, final boolean resolve)
throws ClassNotFoundException {
final byte[] bytes = definitions.get(name);
if (bytes != null) {
return defineClass(name, bytes, 0, bytes.length);
}
return super.loadClass(name, resolve);
}
}
具体来说,我有两个类,MyClass 和 MySubClass,其中 MySubClass 扩展了 MyClass。我对这两个类进行了检测,以便我可以获得与每个类相关的覆盖率信息。我发现如果我首先检测 MySubClass,MemoryClassLoader 将使用 MySubClass 的检测字节调用 defineClass。但是,这样做时,作为父类的 MyClass 也被父类加载器加载。因此,当我下一次检测并加载 MyClass 时,我收到 java.lang.LinkageError,它声称已经有一个由 ClassLoader 加载的 MyClass 定义。这里的问题是加载的 MyClass 的初始版本没有被检测。
如果我以相反的顺序加载类,则不会出现此问题。
我在这里尝试了一些不同的东西:https://github.com/huangwaylon/randoop/blob/bloodhound/src/main/java/randoop/main/MemoryClassLoader.java 通过在递归调用 loadClass 时立即尝试检测父类。但是,由于我尚未弄清楚的原因,这并不完全有效。我观察到,如果我使用这种错误的方法,这两个类的覆盖率信息都不会改变。
总体而言,我的问题是,如何在父子关系中相互关联的类中检测和加载,以使行为不受顺序影响?我可以替换类的定义吗?另一个问题似乎是 super.load,它是 MemoryClassLoader 的父 ClassLoader,我无法控制。
【问题讨论】:
标签: java jvm classloader jacoco instrumentation