2016-08-04 19 views
0

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 

Antwort

0

Es scheint, dass Klassen wurden in der richtigen Reihenfolge nicht geladen werden. Ich bin mir nicht sicher warum, aber das scheint es zu sein.

Meine fix ist Slapping das folllowing in der Refactorer Klasse:

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(); 
} 

Erzwingen sie in der richtigen Reihenfolge geladen werden. Es ist hässlich, aber es funktioniert.