2014-11-23 11 views
5

Ich versuche, java.util.Date mit cglib zu verbessern. Es funktioniert nicht und ich habe keine Erfahrung mit cglib, also frage ich mich, was falsch läuft.cglib löst eine IllegalArgumentException aus, wenn die Klasse java.util.Date verbessert wird

Zum Beispiel die folgenden Code Verbesserung eines ArrayList Werke:

@Test 
public void enhance_ArrayList() { 

    Enhancer enhancer = new Enhancer(); 
    enhancer.setSuperclass(ArrayList.class); 
    enhancer.setCallback(new FixedValue() { 
       @Override 
       public Object loadObject() throws Exception { 
        return "Hello cglib!"; 
       } 
       }); 

    ArrayList enhanced = (ArrayList)enhancer.create(); 
} 

während der folgenden Code:

@Test 
public void enhance_Date() { 
    Enhancer enhancer = new Enhancer(); 
    enhancer.setSuperclass(Date.class); 
    enhancer.setCallback(new FixedValue() { 
       @Override 
       public Object loadObject() throws Exception { 
        return "Hello cglib!"; 
       } 
       }); 

    Date enhanced = (Date)enhancer.create(); 
} 

Ergebnisse in dieser Ausnahme:

java.lang.IllegalArgumentException 
at org.objectweb.asm.ClassReader.<init>(Unknown Source) 
at org.objectweb.asm.ClassReader.<init>(Unknown Source) 
at org.objectweb.asm.ClassReader.<init>(Unknown Source) 
at net.sf.cglib.proxy.BridgeMethodResolver.resolveAll(BridgeMethodResolver.java:61) 
at net.sf.cglib.proxy.Enhancer.emitMethods(Enhancer.java:911) 
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:498) 
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) 
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216) 
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377) 
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285) 

Antwort

5

Es ist wie Ihr scheint verwenden ein JDK in Version 8, das Klassendateien in Version 8 enthält. Diese Klassendateien sind n ot wird von cglib unterstützt, da diese Bibliothek von einer veralteten Version von ASM abhängig ist.

Um dies zu debuggen, müssen wir beachten, dass ASM keine Debugging-Informationen enthält und nicht alle Informationen in seinem Stack-Trace bereitstellt. Alles, was wir wissen, ist, dass ein IllegalArgumentException von einem Konstruktor() seiner ClassReader geworfen wird. Wenn man den Quellcode betrachtet, zeigt sich, dass es nur eine Möglichkeit für eine solche Ausnahme gibt. Aus dem Quellcode von ASM 4.2, die used by the latest version of cglib ist, können wir nur eine solche Ausnahme ausgelöst wird sehen, dass, wenn die Klassendatei einer Version, die auf die Version von ASM unbekannt ist:

// checks the class version 
if (readShort(off + 6) > Opcodes.V1_7) { 
    throw new IllegalArgumentException(); 
} 

Leider gab es nicht Textnachricht für diesen Fehler zur Verfügung gestellt, gibt es keinen wirklichen Grund dafür, warum dies nicht der Fall ist, aber wir müssen damit leben. Um diesen Fehler zu beheben, benötigen Sie eine cglib-Version, die von ASM 5+ abhängig ist, das Java 8 unterstützt.

Ab heute gibt es no compatible version of cglib available als cglib ist not really maintained anymore. Vielleicht möchten Sie stattdessen eine alternative library such as Byte Buddy ausprobieren (beachten Sie, dass ich diese Bibliothek geschrieben habe, schamlose Stecker). Die Erweiterung würde wie folgt funktionieren:

new ByteBuddy().subclass(Date.class) 
    .method(named("toString")) 
    .intercept(FixedValue.value("Hello world!")) 
    .make() 
    .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) 
    .getLoaded() 
    .newInstance(); 

die die toString Methode außer Kraft setzen würde als Byte Buddy Sie Klassen nicht erlaubt, zu definieren, mit illegalen Rückgabewerte.

+0

Danke. Zurück zu java7 für jetzt und es funktioniert gut. Sie müssen einen Blick auf Byte Buddy oder andere Optionen werfen, wenn Sie die Anwendung auf Java8 aktualisieren müssen, wenn cglib zu diesem Zeitpunkt noch nicht java8 unterstützt. – Raipe

3

Es gab eine issue in cglib, wies von Rafael Winterhalter in seiner Antwort, die verhindert, dass cglib winth Java 8 Klassen funktioniert. Es wurde in cglib 3.2.0 behoben. Die Aktualisierung auf die neueste Version (3.2.4) löst das Problem.