2017-04-12 4 views
1

J'essaie maintenant de comprendre cette erreur notre depuis quelques heures et je n'ai littéralement aucune idée de ce qui pourrait le causer. J'essaie d'injecter du code dans un fichier de classe. La chose étrange est que l'injection fonctionne correctement pour ClassWriter.COMPUTE_MAXS, mais lève une exception ArrayIndexOutOfBoundsException si j'utilise ClassWriter.COMPUTE_FRAMES. Et j'ai besoin d'utiliser COMPUTE_FRAMES pour exécuter la classe éditée. J'utilise asm 5.2 et trouvé que jusqu'à présent que COMPUTE_FRAMES a une valeur de 2 (peut-être que cela vous aide en quelque sorte)ASM 5.2 ClassReader.accept throws ArrayIndexOutOfBoundsException: 2

Mon code:

InputStream in = new FileInputStream("Paht/To/Class.class"); 
    ClassReader classReader = new ClassReader(in); 
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES){ 
     @Override 
     protected String getCommonSuperClass(final String type1, final String type2){ 
      return "java/lang/Object"; 
     } 
    }; 

    ClassVisitor mcw = new ModifierClassWriter(Opcodes.ASM5, cw); 
    classReader.accept(mcw, 0); 

    File outputDir = new File("Path/To/Output/dir"); 
    outputDir.mkdirs(); 
    DataOutputStream dout = new DataOutputStream(new FileOutputStream(new File(outputDir, "NameOfFile.class"))); 
    dout.write(cw.toByteArray()); 
    dout.close(); 

Modificateur Méthode Writer:

public static class ModifierMethodWriter extends MethodVisitor{ 

    private String methodName; 

    public ModifierMethodWriter(int api, MethodVisitor mv, String methodName) { 
     super(api, mv); 
     this.methodName = methodName; 
    } 
    @Override 
    public void visitCode() { 
     super.visitCode(); 
    //InjectCodeHere, removed it because it most likely doesnt cause the error 
    } 
} 

ModifierClassWriter:

public static class ModifierClassWriter extends ClassVisitor{ 
    private int api; 
    public ModifierClassWriter(int api, ClassWriter cv) { 
     super(api, cv); 
     this.api = api; 
    } 

    @Override 
    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { 
     MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); 
     ModifierMethodWriter mvw = new ModifierMethodWriter(api, mv, name); 
     return mvw; 
    } 
} 

L'erreur:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2 
at org.objectweb.asm.Frame.a(Unknown Source) 
at org.objectweb.asm.Frame.a(Unknown Source) 
at org.objectweb.asm.MethodWriter.visitMaxs(Unknown Source) 
at org.objectweb.asm.MethodVisitor.visitMaxs(Unknown Source) 
at org.objectweb.asm.ClassReader.a(Unknown Source) 
at org.objectweb.asm.ClassReader.b(Unknown Source) 
at org.objectweb.asm.ClassReader.accept(Unknown Source) 
at org.objectweb.asm.ClassReader.accept(Unknown Source) 
at package.main.ClassMaker.main(ClassMaker.java:28) 
+0

Vous devriez obtenir la source du SVN d'ASM avant d'utiliser leur jar compilé. Il vous permettra de voir la pile-trace complète sans noms comme 'a' ou' b'. En ce qui concerne le problème lui-même, la génération de trame a tendance à échouer lorsqu'une modification que vous effectuez entraîne un bytecode invalide. '// InjectCodeHere, enlevé parce que le plus probable ne cause pas l'erreur» C'est en fait ce qui l'a causé. –

Répondre

1

Grâce à @ display-name, j'ai trouvé l'erreur.

super.visitMaxs(4, 2); 

dans "ModifierMethodWriter" a causé l'erreur, le code que je n'ai pas réellement montré ici.