From: Andy Clement Date: Wed, 18 Apr 2012 21:07:59 +0000 (-0700) Subject: Fix up J7 stackmap creation X-Git-Tag: V1_7_0RC1~4 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=80ce56ea366dd81da7354855ef2a2e2ca65a4f93;p=aspectj.git Fix up J7 stackmap creation --- diff --git a/weaver/src/org/aspectj/weaver/bcel/asm/StackMapAdder.java b/weaver/src/org/aspectj/weaver/bcel/asm/StackMapAdder.java index 07477d1a9..2455a7382 100644 --- a/weaver/src/org/aspectj/weaver/bcel/asm/StackMapAdder.java +++ b/weaver/src/org/aspectj/weaver/bcel/asm/StackMapAdder.java @@ -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) {