Ich arbeite an einem Java-Agent für ein persönliches Projekt von mir und stieß auf einen wirklich seltsamen Fehler. Wenn ich die Methode "Register" in meiner IDE ausführen, funktioniert es gut. Kein Zirkularitätsfehler. Aber wenn ich den Agenten exportiere und ihn mit den Startargumenten javaagent:"agent.jar"
verwende, stürzt er ab und gibt ClassCircularityError (Looping superclass hierarchy).ClassCircularityError, wenn die Superklassenhierarchie normal ist
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 {}
}
Stacktrace
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)
was wirklich verwirrend mich ist, dass, wenn ich die übergeordnete Klasse Hierarchie in der kompilierten Agent überprüft es in Ordnung ausgedruckt.
mit Geprüft:
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++;
}
Welche Ausgänge:
// 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