我正在为我的个人项目开发一个java代理,遇到了一个非常奇怪的错误。当我在我的IDE中运行“register”方法时,它可以正常工作。没有圆度误差。但是当我导出代理并将其与launch args javaagent:"agent.jar"
一起使用时,它会崩溃,从而导致ClassCircularityError (循环超类层次结构)。
public class Refactorer implements ClassFileTransformer {
private static final Set<AbstractMatcher<String>> matchers = new HashSet<AbstractMatcher<String>>();
public static void register(AbstractMatcher<String> matcher) {
matchers.add(matcher);
}
public byte[] transform(ClassLoader loader, String name, Class<?> clazz, ProtectionDomain domain, byte[] bytes) throws IllegalClassFormatException {}
}
堆栈跟踪
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:386)
at sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:401)
Caused by: java.lang.ClassCircularityError: java/util/Set
at me.vader.Refactorer.register(Refactorer.java:42)
at me.vader.Setup.registerModders(Setup.java:30)
at me.vader.Agent.setAndAddTransformer(Agent.java:37)
at me.vader.Agent.premain(Agent.java:18)
让我感到困惑的是,当我检查已编译代理中的超类层次结构时,它打印出来的很好。
经过测试:
Class c = matchers.getClass();
int i = 0;
while (c != null){
System.out.println("Class (Sup x" + i+ "): " + c.getName());
c = c.getSuperclass();
i++;
}
i = 0;
c = matcher.getClass();
while (c != null){
System.out.println("Class (Sup x" + i+ "): " + c.getName());
c = c.getSuperclass();
i++;
}
哪个输出:
// The "matchers"
Class (Sup x0): java.util.HashSet
Class (Sup x1): java.util.AbstractSet
Class (Sup x2): java.util.AbstractCollection
Class (Sup x3): java.lang.Object
// The matcher being added to "matchers"
Class (Sup x0): me.vader.match.ClassMatcher
Class (Sup x1): me.vader.match.AbstractMatcher
Class (Sup x2): java.lang.Object
答案 0 :(得分:0)
似乎没有以正确的顺序加载课程。我不确定为什么,但似乎就是这样。
我的解决方法是在Refactorer类中使用以下内容:
static {
Serializable.class.getName();
Cloneable.class.getName();
Iterable .class.getName();
Collection.class.getName();
AbstractCollection.class.getName();
Set.class.getName();
AbstractSet.class.getName();
HashSet.class.getName();
}
强制以正确的顺序加载它们。它很难看,但它确实有效。