You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sirona.apache.org by rm...@apache.org on 2014/02/23 22:26:38 UTC
svn commit: r1571093 -
/incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaClassVisitor.java
Author: rmannibucau
Date: Sun Feb 23 21:26:38 2014
New Revision: 1571093
URL: http://svn.apache.org/r1571093
Log:
tabulations
Modified:
incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaClassVisitor.java
Modified: incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaClassVisitor.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaClassVisitor.java?rev=1571093&r1=1571092&r2=1571093&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaClassVisitor.java (original)
+++ incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaClassVisitor.java Sun Feb 23 21:26:38 2014
@@ -35,26 +35,26 @@ import java.util.LinkedList;
import java.util.Map;
public class SironaClassVisitor extends ClassVisitor implements Opcodes {
- private static final int CONSTANT_ACCESS = ACC_PRIVATE | ACC_STATIC | ACC_FINAL;
+ private static final int CONSTANT_ACCESS = ACC_PRIVATE | ACC_STATIC | ACC_FINAL;
- private static final String STATIC_INIT = "<clinit>";
- private static final String CONSTRUCTOR = "<init>";
- private static final String NO_PARAM_RETURN_VOID = "()V";
-
- private static final String METHOD_SUFFIX = "_$_$irona_$_internal_$_original_$_";
- private static final String FIELD_SUFFIX = "_$_$IRONA_$_INTERNAL_$_KEY";
- private static final String STATIC_CLINT_MERGE_PREFIX = "_$_$irona_static_merge";
-
- private static final Type KEY_TYPE = Type.getType(String.class);
- private static final Type AGENT_CONTEXT = Type.getType(AgentContext.class);
-
- private final String javaName;
- private Type classType;
-
- public SironaClassVisitor(final ClassWriter writer, final String javaName, final Map<String, String> keys) {
- super(ASM4, new SironaStaticInitMerger(writer, keys));
- this.javaName = javaName;
- }
+ private static final String STATIC_INIT = "<clinit>";
+ private static final String CONSTRUCTOR = "<init>";
+ private static final String NO_PARAM_RETURN_VOID = "()V";
+
+ private static final String METHOD_SUFFIX = "_$_$irona_$_internal_$_original_$_";
+ private static final String FIELD_SUFFIX = "_$_$IRONA_$_INTERNAL_$_KEY";
+ private static final String STATIC_CLINT_MERGE_PREFIX = "_$_$irona_static_merge";
+
+ private static final Type KEY_TYPE = Type.getType(String.class);
+ private static final Type AGENT_CONTEXT = Type.getType(AgentContext.class);
+
+ private final String javaName;
+ private Type classType;
+
+ public SironaClassVisitor(final ClassWriter writer, final String javaName, final Map<String, String> keys) {
+ super(ASM4, new SironaStaticInitMerger(writer, keys));
+ this.javaName = javaName;
+ }
@Override
public void visit(final int version, final int access, final String name, final String signature, final String superName,
@@ -64,412 +64,418 @@ public class SironaClassVisitor extends
SironaStaticInitMerger.class.cast(cv).initSironaFields(classType);
}
- @Override
- public void visitSource(final String source, final String debug) {
- super.visitSource(source, debug);
- visitAnnotation("L" + Instrumented.class.getName().replace('.', '/') + ";", true).visitEnd();
- }
-
- @Override
- public MethodVisitor visitMethod(int access, final String name, final String desc, final String signature, final String[] exceptions) {
- final MethodVisitor visitor = super.visitMethod(access, name, desc, signature, exceptions);
- if (!isSironable(access, name)) {
- return visitor;
- }
-
- final String label = javaName.replace("/", ".") + "." + name;
- if (AgentContext.listeners(label) != null) {
- // generate internal method - the proxy (previous one) delegates to this one
- return new MoveAnnotationOnProxy(
+ @Override
+ public void visitSource(final String source, final String debug) {
+ super.visitSource(source, debug);
+ visitAnnotation("L" + Instrumented.class.getName().replace('.', '/') + ";", true).visitEnd();
+ }
+
+ @Override
+ public MethodVisitor visitMethod(int access, final String name, final String desc, final String signature, final String[] exceptions) {
+ final MethodVisitor visitor = super.visitMethod(access, name, desc, signature, exceptions);
+ if (!isSironable(access, name)) {
+ return visitor;
+ }
+
+ final String label = javaName.replace("/", ".") + "." + name;
+ if (AgentContext.listeners(label) != null) {
+ // generate internal method - the proxy (previous one) delegates to this one
+ return new MoveAnnotationOnProxy(
new ProxyMethodsVisitor(visitor, access, new Method(name, desc), classType),
super.visitMethod(forcePrivate(access), name + METHOD_SUFFIX, desc, signature, exceptions));
- }
- return visitor;
- }
-
- private static int forcePrivate(final int access) {
- return (access & ~(Modifier.PRIVATE | Modifier.PUBLIC | Modifier.PROTECTED)) | Modifier.PRIVATE;
- }
-
- private static boolean isSironable(final int access, final String name) {
- return !name.equals(STATIC_INIT) && !name.equals(CONSTRUCTOR) && !Modifier.isAbstract(access) && !Modifier.isNative(access);
- }
-
- private static class ProxyMethodsVisitor extends GeneratorAdapter {
- private static final Type THROWABLE_TYPE = Type.getType(Throwable.class);
- private static final Type[] STOP_WITH_THROWABLE_ARGS_TYPES = new Type[] {THROWABLE_TYPE};
- private static final Type OBJECT_TYPE = Type.getType(Object.class);
- private static final Type[] STOP_WITH_OBJECT_ARGS_TYPES = new Type[] {OBJECT_TYPE};
- private static final Type[] START_ARGS_TYPES = new Type[] {KEY_TYPE, OBJECT_TYPE};
-
- // methods
- private static final String START_METHOD = "startOn";
- private static final String STOP_WITH_EXCEPTION_METHOD = "stopWithException";
- private static final String STOP_METHOD = "stop";
- private static final String VALUE_OF = "valueOf";
-
- private static final Map<Type, Primitive> PRIMITIVES = new HashMap<Type, Primitive>();
- static {
- final Type shortType = Type.getType(short.class);
- PRIMITIVES.put(shortType, new Primitive(Type.getType(Short.class), shortType));
- final Type intType = Type.getType(int.class);
- PRIMITIVES.put(intType, new Primitive(Type.getType(Integer.class), intType));
- final Type longType = Type.getType(long.class);
- PRIMITIVES.put(longType, new Primitive(Type.getType(Long.class), longType));
- final Type charType = Type.getType(char.class);
- PRIMITIVES.put(charType, new Primitive(Type.getType(Character.class), charType));
- final Type floatType = Type.getType(float.class);
- PRIMITIVES.put(floatType, new Primitive(Type.getType(Float.class), floatType));
- final Type doubleType = Type.getType(double.class);
- PRIMITIVES.put(doubleType, new Primitive(Type.getType(Double.class), doubleType));
- final Type boolType = Type.getType(boolean.class);
- PRIMITIVES.put(boolType, new Primitive(Type.getType(Boolean.class), boolType));
- final Type byteType = Type.getType(byte.class);
- PRIMITIVES.put(boolType, new Primitive(Type.getType(Byte.class), byteType));
- }
-
- private final boolean isStatic;
- private final Type clazz;
- private final boolean isVoid;
- private final Primitive primitiveWrapper;
- private final Method method;
-
- public ProxyMethodsVisitor(final MethodVisitor methodVisitor, final int access, final Method method, final Type clazz) {
- super(ASM4, methodVisitor, access, method.getName(), method.getDescriptor());
- this.clazz = clazz;
- this.method = method;
- this.isStatic = Modifier.isStatic(access);
-
- final Type returnType = method.getReturnType();
- this.isVoid = Type.VOID_TYPE.equals(returnType);
- this.primitiveWrapper = PRIMITIVES.get(returnType);
- }
-
- @Override
- public void visitCode() {
- final int agentIdx = newLocal(AGENT_CONTEXT);
- getStatic(clazz, method.getName() + FIELD_SUFFIX, KEY_TYPE);
- if (!isStatic) {
- loadThis();
- } else {
- visitInsn(ACONST_NULL); // this == null for static methods
- }
- invokeStatic(AGENT_CONTEXT, new Method(START_METHOD, AGENT_CONTEXT, START_ARGS_TYPES));
- storeLocal(agentIdx);
-
- final Label tryStart = mark();
-
- invoke();
-
- // store result to return it later if it doesn't return void
- final int result = storeResult();
-
- // take metrics before returning
- loadLocal(agentIdx);
-
- if (result != -1) {
- loadLocal(result);
- if (primitiveWrapper != null) { // we call agentContext.stop(Object) so we need to wrap primitives
- invokeStatic(primitiveWrapper.wrapper, primitiveWrapper.method);
- }
- } else {
- visitInsn(ACONST_NULL); // result == null for static methods
- }
- invokeVirtual(AGENT_CONTEXT, new Method(STOP_METHOD, Type.VOID_TYPE, STOP_WITH_OBJECT_ARGS_TYPES));
-
- // return result
- returnResult(result);
-
- final Label tryEnd = mark();
- catchException(tryStart, tryEnd, THROWABLE_TYPE);
-
- // context.stopWithException(throwable);
- final int throwableId = newLocal(THROWABLE_TYPE);
- storeLocal(throwableId);
- loadLocal(agentIdx);
- loadLocal(throwableId);
- invokeVirtual(AGENT_CONTEXT, new Method(STOP_WITH_EXCEPTION_METHOD, Type.VOID_TYPE, STOP_WITH_THROWABLE_ARGS_TYPES));
-
- // rethrow throwable
- loadLocal(throwableId);
- throwException();
-
- endMethod();
- }
-
- private void invoke() {
- final Method mtd = new Method(method.getName() + METHOD_SUFFIX, method.getDescriptor());
- if (isStatic) {
- loadArgs();
- invokeStatic(clazz, mtd);
- } else {
- loadThis();
- loadArgs();
- invokeVirtual(clazz, mtd);
- }
- }
-
- private int storeResult() {
- final int result;
- if (!isVoid) {
- result = newLocal(method.getReturnType());
- storeLocal(result);
- } else {
- result = -1;
- }
- return result;
- }
-
- private void returnResult(int result) {
- // return
- if (!isVoid) {
- loadLocal(result);
- }
- returnValue();
- }
-
- private static class Primitive {
- private Type wrapper;
- private Method method;
-
- private Primitive(final Type wrapper, final Type params) {
- this.wrapper = wrapper;
- this.method = new Method(VALUE_OF, wrapper, new Type[] {params});
- }
- }
- }
-
- // remove annotation from original methods and put it on proxy ones
- private static class MoveAnnotationOnProxy extends MethodVisitor {
- private final MethodVisitor delegate;
- private final ProxyMethodsVisitor decorator;
- private final Collection<Runnable> rewriteTasks = new LinkedList<Runnable>();
-
- public MoveAnnotationOnProxy(final ProxyMethodsVisitor decorator, final MethodVisitor methodVisitor) {
- super(ASM4);
- this.decorator = decorator;
- this.delegate = methodVisitor;
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
- final AnnotationRewriter rewriter = new AnnotationRewriter(rewriteTasks);
- rewriteTasks.add(new Runnable() {
- @Override
- public void run() {
- rewriter.setDelegate(decorator.visitAnnotation(desc, visible));
- }
- });
- return rewriter;
- }
-
- @Override
- public AnnotationVisitor visitParameterAnnotation(final int parameter, final String desc, final boolean visible) {
- final AnnotationRewriter rewriter = new AnnotationRewriter(rewriteTasks);
- rewriteTasks.add(new Runnable() {
- @Override
- public void run() {
- rewriter.setDelegate(decorator.visitParameterAnnotation(parameter, desc, visible));
- }
- });
- return rewriter;
- }
-
- @Override
- public AnnotationVisitor visitAnnotationDefault() {
- final AnnotationRewriter rewriter = new AnnotationRewriter(rewriteTasks);
- rewriteTasks.add(new Runnable() {
- @Override
- public void run() {
- rewriter.setDelegate(decorator.visitAnnotationDefault());
- }
- });
- return rewriter;
- }
-
- @Override
- public void visitAttribute(Attribute attr) {
- delegate.visitAttribute(attr);
- }
-
- @Override
- public void visitCode() {
- delegate.visitCode();
- }
-
- @Override
- public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
- delegate.visitFrame(type, nLocal, local, nStack, stack);
- }
-
- @Override
- public void visitInsn(int opcode) {
- delegate.visitInsn(opcode);
- }
-
- @Override
- public void visitIntInsn(int opcode, int operand) {
- delegate.visitIntInsn(opcode, operand);
- }
-
- @Override
- public void visitVarInsn(int opcode, int var) {
- delegate.visitVarInsn(opcode, var);
- }
-
- @Override
- public void visitTypeInsn(int opcode, String type) {
- delegate.visitTypeInsn(opcode, type);
- }
-
- @Override
- public void visitFieldInsn(int opcode, String owner, String name, String desc) {
- delegate.visitFieldInsn(opcode, owner, name, desc);
- }
-
- @Override
- public void visitMethodInsn(int opcode, String owner, String name, String desc) {
- delegate.visitMethodInsn(opcode, owner, name, desc);
- }
-
- @Override
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
- delegate.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
- }
-
- @Override
- public void visitJumpInsn(int opcode, Label label) {
- delegate.visitJumpInsn(opcode, label);
- }
-
- @Override
- public void visitLabel(Label label) {
- delegate.visitLabel(label);
- }
-
- @Override
- public void visitLdcInsn(Object cst) {
- delegate.visitLdcInsn(cst);
- }
-
- @Override
- public void visitIincInsn(int var, int increment) {
- delegate.visitIincInsn(var, increment);
- }
-
- @Override
- public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
- delegate.visitTableSwitchInsn(min, max, dflt, labels);
- }
-
- @Override
- public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
- delegate.visitLookupSwitchInsn(dflt, keys, labels);
- }
-
- @Override
- public void visitMultiANewArrayInsn(String desc, int dims) {
- delegate.visitMultiANewArrayInsn(desc, dims);
- }
-
- @Override
- public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
- delegate.visitTryCatchBlock(start, end, handler, type);
- }
-
- @Override
- public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
- delegate.visitLocalVariable(name, desc, signature, start, end, index);
- }
-
- @Override
- public void visitLineNumber(int line, Label start) {
- delegate.visitLineNumber(line, start);
- }
-
- @Override
- public void visitMaxs(int maxStack, int maxLocals) {
- delegate.visitMaxs(maxStack, maxLocals);
- }
-
- @Override
- public void visitEnd() {
- delegate.visitEnd();
-
- // generate proxy
- for (final Runnable visitor : rewriteTasks) {
- visitor.run();
- }
- decorator.visitCode();
- decorator.visitEnd();
- }
- }
-
- private static class AnnotationRewriter extends AnnotationVisitor {
- private final Collection<Runnable> runnables;
- private AnnotationVisitor delegate;
-
- public AnnotationRewriter(final Collection<Runnable> tasks) {
- super(ASM4);
- this.runnables = tasks;
- }
-
- @Override
- public void visit(final String name, final Object value) {
- runnables.add(new Runnable() {
- @Override
- public void run() {
- delegate.visit(name, value);
- }
- });
- }
-
- @Override
- public void visitEnum(final String name, final String desc, final String value) {
- runnables.add(new Runnable() {
- @Override
- public void run() {
- delegate.visitEnum(name, desc, value);
- }
- });
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(final String name, final String desc) {
- runnables.add(new Runnable() {
- @Override
- public void run() {
- delegate.visitAnnotation(name, desc);
- }
- });
- return this;
- }
-
- @Override
- public AnnotationVisitor visitArray(final String name) {
- runnables.add(new Runnable() {
- @Override
- public void run() {
- delegate.visitArray(name);
- }
- });
- return this;
- }
-
- @Override
- public void visitEnd() {
- runnables.add(new Runnable() {
- @Override
- public void run() {
- delegate.visitEnd();
- }
- });
- }
-
- public void setDelegate(final AnnotationVisitor delegate) {
- this.delegate = delegate;
- }
- }
+ }
+ return visitor;
+ }
+
+ private static int forcePrivate(final int access) {
+ return (access & ~(Modifier.PRIVATE | Modifier.PUBLIC | Modifier.PROTECTED)) | Modifier.PRIVATE;
+ }
+
+ private static boolean isSironable(final int access, final String name) {
+ return !name.equals(STATIC_INIT) && !name.equals(CONSTRUCTOR) && !Modifier.isAbstract(access) && !Modifier.isNative(access);
+ }
+
+ private static class ProxyMethodsVisitor extends GeneratorAdapter {
+ private static final Type THROWABLE_TYPE = Type.getType(Throwable.class);
+ private static final Type[] STOP_WITH_THROWABLE_ARGS_TYPES = new Type[] {THROWABLE_TYPE};
+ private static final Type OBJECT_TYPE = Type.getType(Object.class);
+ private static final Type[] STOP_WITH_OBJECT_ARGS_TYPES = new Type[] {OBJECT_TYPE};
+ private static final Type[] START_ARGS_TYPES = new Type[] {KEY_TYPE, OBJECT_TYPE};
+
+ // methods
+ private static final String START_METHOD = "startOn";
+ private static final String STOP_WITH_EXCEPTION_METHOD = "stopWithException";
+ private static final String STOP_METHOD = "stop";
+ private static final String VALUE_OF = "valueOf";
+
+ private static final Map<Type, Primitive> PRIMITIVES = new HashMap<Type, Primitive>();
+ static {
+ final Type shortType = Type.getType(short.class);
+ PRIMITIVES.put(shortType, new Primitive(Type.getType(Short.class), shortType));
+ final Type intType = Type.getType(int.class);
+ PRIMITIVES.put(intType, new Primitive(Type.getType(Integer.class), intType));
+ final Type longType = Type.getType(long.class);
+ PRIMITIVES.put(longType, new Primitive(Type.getType(Long.class), longType));
+ final Type charType = Type.getType(char.class);
+ PRIMITIVES.put(charType, new Primitive(Type.getType(Character.class), charType));
+ final Type floatType = Type.getType(float.class);
+ PRIMITIVES.put(floatType, new Primitive(Type.getType(Float.class), floatType));
+ final Type doubleType = Type.getType(double.class);
+ PRIMITIVES.put(doubleType, new Primitive(Type.getType(Double.class), doubleType));
+ final Type boolType = Type.getType(boolean.class);
+ PRIMITIVES.put(boolType, new Primitive(Type.getType(Boolean.class), boolType));
+ final Type byteType = Type.getType(byte.class);
+ PRIMITIVES.put(boolType, new Primitive(Type.getType(Byte.class), byteType));
+ }
+
+ private final boolean isStatic;
+ private final Type clazz;
+ private final boolean isVoid;
+ private final Primitive primitiveWrapper;
+ private final Method method;
+
+ public ProxyMethodsVisitor(final MethodVisitor methodVisitor, final int access, final Method method, final Type clazz) {
+ super(ASM4, methodVisitor, access, method.getName(), method.getDescriptor());
+ this.clazz = clazz;
+ this.method = method;
+ this.isStatic = Modifier.isStatic(access);
+
+ final Type returnType = method.getReturnType();
+ this.isVoid = Type.VOID_TYPE.equals(returnType);
+ this.primitiveWrapper = PRIMITIVES.get(returnType);
+ }
+
+ @Override
+ public void visitCode() {
+ final int agentIdx = newLocal(AGENT_CONTEXT);
+ getStatic(clazz, method.getName() + FIELD_SUFFIX, KEY_TYPE);
+ if (!isStatic) {
+ loadThis();
+ } else {
+ visitInsn(ACONST_NULL); // this == null for static methods
+ }
+ invokeStatic(AGENT_CONTEXT, new Method(START_METHOD, AGENT_CONTEXT, START_ARGS_TYPES));
+ storeLocal(agentIdx);
+
+ final Label tryStart = mark();
+
+ invoke();
+
+ // store result to return it later if it doesn't return void
+ final int result = storeResult();
+
+ // take metrics before returning
+ loadLocal(agentIdx);
+
+ if (result != -1) {
+ loadLocal(result);
+ if (primitiveWrapper != null) { // we call agentContext.stop(Object) so we need to wrap primitives
+ invokeStatic(primitiveWrapper.wrapper, primitiveWrapper.method);
+ }
+ } else {
+ visitInsn(ACONST_NULL); // result == null for static methods
+ }
+ invokeVirtual(AGENT_CONTEXT, new Method(STOP_METHOD, Type.VOID_TYPE, STOP_WITH_OBJECT_ARGS_TYPES));
+
+ // return result
+ returnResult(result);
+
+ final Label tryEnd = mark();
+ catchException(tryStart, tryEnd, THROWABLE_TYPE);
+
+ // context.stopWithException(throwable);
+ final int throwableId = newLocal(THROWABLE_TYPE);
+ storeLocal(throwableId);
+ loadLocal(agentIdx);
+ loadLocal(throwableId);
+ invokeVirtual(AGENT_CONTEXT, new Method(STOP_WITH_EXCEPTION_METHOD, Type.VOID_TYPE, STOP_WITH_THROWABLE_ARGS_TYPES));
+
+ // rethrow throwable
+ loadLocal(throwableId);
+ throwException();
+
+ endMethod();
+ }
+
+ private void invoke() {
+ final Method mtd = new Method(method.getName() + METHOD_SUFFIX, method.getDescriptor());
+ if (isStatic) {
+ loadArgs();
+ invokeStatic(clazz, mtd);
+ } else {
+ loadThis();
+ loadArgs();
+ invokeVirtual(clazz, mtd);
+ }
+ }
+
+ private int storeResult() {
+ final int result;
+ if (!isVoid) {
+ result = newLocal(method.getReturnType());
+ storeLocal(result);
+ } else {
+ result = -1;
+ }
+ return result;
+ }
+
+ private void returnResult(int result) {
+ // return
+ if (!isVoid) {
+ loadLocal(result);
+ }
+ returnValue();
+ }
+
+ @Override
+ public void visitEnd() {
+ visitMaxs(0, 0);
+ super.visitEnd();
+ }
+
+ private static class Primitive {
+ private Type wrapper;
+ private Method method;
+
+ private Primitive(final Type wrapper, final Type params) {
+ this.wrapper = wrapper;
+ this.method = new Method(VALUE_OF, wrapper, new Type[] {params});
+ }
+ }
+ }
+
+ // remove annotation from original methods and put it on proxy ones
+ private static class MoveAnnotationOnProxy extends MethodVisitor {
+ private final MethodVisitor delegate;
+ private final ProxyMethodsVisitor decorator;
+ private final Collection<Runnable> rewriteTasks = new LinkedList<Runnable>();
+
+ public MoveAnnotationOnProxy(final ProxyMethodsVisitor decorator, final MethodVisitor methodVisitor) {
+ super(ASM4);
+ this.decorator = decorator;
+ this.delegate = methodVisitor;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
+ final AnnotationRewriter rewriter = new AnnotationRewriter(rewriteTasks);
+ rewriteTasks.add(new Runnable() {
+ @Override
+ public void run() {
+ rewriter.setDelegate(decorator.visitAnnotation(desc, visible));
+ }
+ });
+ return rewriter;
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(final int parameter, final String desc, final boolean visible) {
+ final AnnotationRewriter rewriter = new AnnotationRewriter(rewriteTasks);
+ rewriteTasks.add(new Runnable() {
+ @Override
+ public void run() {
+ rewriter.setDelegate(decorator.visitParameterAnnotation(parameter, desc, visible));
+ }
+ });
+ return rewriter;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ final AnnotationRewriter rewriter = new AnnotationRewriter(rewriteTasks);
+ rewriteTasks.add(new Runnable() {
+ @Override
+ public void run() {
+ rewriter.setDelegate(decorator.visitAnnotationDefault());
+ }
+ });
+ return rewriter;
+ }
+
+ @Override
+ public void visitAttribute(Attribute attr) {
+ delegate.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitCode() {
+ delegate.visitCode();
+ }
+
+ @Override
+ public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
+ delegate.visitFrame(type, nLocal, local, nStack, stack);
+ }
+
+ @Override
+ public void visitInsn(int opcode) {
+ delegate.visitInsn(opcode);
+ }
+
+ @Override
+ public void visitIntInsn(int opcode, int operand) {
+ delegate.visitIntInsn(opcode, operand);
+ }
+
+ @Override
+ public void visitVarInsn(int opcode, int var) {
+ delegate.visitVarInsn(opcode, var);
+ }
+
+ @Override
+ public void visitTypeInsn(int opcode, String type) {
+ delegate.visitTypeInsn(opcode, type);
+ }
+
+ @Override
+ public void visitFieldInsn(int opcode, String owner, String name, String desc) {
+ delegate.visitFieldInsn(opcode, owner, name, desc);
+ }
+
+ @Override
+ public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+ delegate.visitMethodInsn(opcode, owner, name, desc);
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
+ delegate.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ }
+
+ @Override
+ public void visitJumpInsn(int opcode, Label label) {
+ delegate.visitJumpInsn(opcode, label);
+ }
+
+ @Override
+ public void visitLabel(Label label) {
+ delegate.visitLabel(label);
+ }
+
+ @Override
+ public void visitLdcInsn(Object cst) {
+ delegate.visitLdcInsn(cst);
+ }
+
+ @Override
+ public void visitIincInsn(int var, int increment) {
+ delegate.visitIincInsn(var, increment);
+ }
+
+ @Override
+ public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
+ delegate.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
+ delegate.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(String desc, int dims) {
+ delegate.visitMultiANewArrayInsn(desc, dims);
+ }
+
+ @Override
+ public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
+ delegate.visitTryCatchBlock(start, end, handler, type);
+ }
+
+ @Override
+ public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
+ delegate.visitLocalVariable(name, desc, signature, start, end, index);
+ }
+
+ @Override
+ public void visitLineNumber(int line, Label start) {
+ delegate.visitLineNumber(line, start);
+ }
+
+ @Override
+ public void visitMaxs(int maxStack, int maxLocals) {
+ delegate.visitMaxs(maxStack, maxLocals);
+ }
+
+ @Override
+ public void visitEnd() {
+ delegate.visitEnd();
+
+ // generate proxy
+ for (final Runnable visitor : rewriteTasks) {
+ visitor.run();
+ }
+ decorator.visitCode();
+ decorator.visitEnd();
+ }
+ }
+
+ private static class AnnotationRewriter extends AnnotationVisitor {
+ private final Collection<Runnable> runnables;
+ private AnnotationVisitor delegate;
+
+ public AnnotationRewriter(final Collection<Runnable> tasks) {
+ super(ASM4);
+ this.runnables = tasks;
+ }
+
+ @Override
+ public void visit(final String name, final Object value) {
+ runnables.add(new Runnable() {
+ @Override
+ public void run() {
+ delegate.visit(name, value);
+ }
+ });
+ }
+
+ @Override
+ public void visitEnum(final String name, final String desc, final String value) {
+ runnables.add(new Runnable() {
+ @Override
+ public void run() {
+ delegate.visitEnum(name, desc, value);
+ }
+ });
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String name, final String desc) {
+ runnables.add(new Runnable() {
+ @Override
+ public void run() {
+ delegate.visitAnnotation(name, desc);
+ }
+ });
+ return this;
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ runnables.add(new Runnable() {
+ @Override
+ public void run() {
+ delegate.visitArray(name);
+ }
+ });
+ return this;
+ }
+
+ @Override
+ public void visitEnd() {
+ runnables.add(new Runnable() {
+ @Override
+ public void run() {
+ delegate.visitEnd();
+ }
+ });
+ }
+
+ public void setDelegate(final AnnotationVisitor delegate) {
+ this.delegate = delegate;
+ }
+ }
// fast visitor used first to get static fields to generate
public static class SironaKeyVisitor extends ClassVisitor implements Opcodes {
@@ -544,6 +550,7 @@ public class SironaClassVisitor extends
public void visitEnd() {
clinit.visitInsn(Opcodes.RETURN);
clinit.visitMaxs(0, 0);
+ clinit.visitEnd();
cv.visitEnd();
}