]> source.dussan.org Git - aspectj.git/commitdiff
Fix up J7 stackmap creation
authorAndy Clement <andrew.clement@gmail.com>
Wed, 18 Apr 2012 21:07:59 +0000 (14:07 -0700)
committerAndy Clement <andrew.clement@gmail.com>
Wed, 18 Apr 2012 21:07:59 +0000 (14:07 -0700)
weaver/src/org/aspectj/weaver/bcel/asm/StackMapAdder.java

index 07477d1a9bc753770e7ef9c512cc7211d4f590d1..2455a73827f71f2748c5bb2fabb77d0fb7fe24a2 100644 (file)
@@ -15,14 +15,20 @@ import org.aspectj.weaver.ResolvedType;
 import org.aspectj.weaver.UnresolvedType;
 import org.aspectj.weaver.World;
 
-import aj.org.objectweb.asm.ClassReader;
-import aj.org.objectweb.asm.ClassWriter;
+import aj.org.objectweb.asm.*;
 
 /**
  * Uses asm to add the stack map attribute to methods in a class. The class is passed in as pure byte data and then a reader/writer
  * process it. The writer is wired into the world so that types can be resolved and getCommonSuperClass() can be implemented without
  * class loading using the context class loader.
  * 
+ * It is important that the constant pool is preserved here and asm does not try to remove unused entries.  That is because some
+ * entries are refered to from classfile attributes.  Asm cannot see into these attributes so does not realise the constant pool
+ * entries are in use.  In order to ensure the copying of cp occurs, we use the variant super constructor call in AspectJConnectClassWriter
+ * that passes in the classreader.  However, ordinarily that change causes a further optimization: that if a classreader sees
+ * a methodvisitor that has been created by a ClassWriter then it just copies the data across without changing it (and so it
+ * fails to attach the stackmapattribute).  In order to avoid this further optimization we use our own minimal MethodVisitor.
+ * 
  * @author Andy Clement
  */
 public class StackMapAdder {
@@ -31,7 +37,8 @@ public class StackMapAdder {
                try {
                        ClassReader cr = new ClassReader(data);
                        ClassWriter cw = new AspectJConnectClassWriter(cr, world);
-                       cr.accept(cw, 0);
+                       ClassVisitor cv = new AspectJClassVisitor(cw);
+                       cr.accept(cv, 0);
                        return cw.toByteArray();
                } catch (Throwable t) {
                        System.err.println("AspectJ Internal Error: unable to add stackmap attributes. " + t.getMessage());
@@ -39,6 +46,28 @@ public class StackMapAdder {
                        return data;
                }
        }
+       
+       private static class AspectJClassVisitor extends ClassVisitor {
+
+               public AspectJClassVisitor(ClassVisitor classwriter) {
+                       super(Opcodes.ASM4, classwriter);
+               }
+
+               @Override
+               public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
+                       MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
+                       return new AJMethodVisitor(mv);
+               }
+               
+               // Minimal pass through MethodVisitor just so that the ClassReader doesn't see one that has been directly
+               // created by a ClassWriter (see top level class comment)
+               static class AJMethodVisitor extends MethodVisitor {
+                       public AJMethodVisitor(MethodVisitor mv) {
+                               super(Opcodes.ASM4,mv);
+                       }
+               }
+               
+       }
 
        private static class AspectJConnectClassWriter extends ClassWriter {
                private final World world;
@@ -47,6 +76,7 @@ public class StackMapAdder {
                        super(cr, ClassWriter.COMPUTE_FRAMES); // passing in cr is necessary so cpool isnt modified (see 2.2.4 of asm doc)
                        this.world = w;
                }
+               
 
                // Implementation of getCommonSuperClass() that avoids Class.forName()
                protected String getCommonSuperClass(final String type1, final String type2) {