Example usage for org.objectweb.asm.commons GeneratorAdapter loadArgArray

List of usage examples for org.objectweb.asm.commons GeneratorAdapter loadArgArray

Introduction

In this page you can find the example usage for org.objectweb.asm.commons GeneratorAdapter loadArgArray.

Prototype

public void loadArgArray() 

Source Link

Document

Generates the instructions to load all the method arguments on the stack, as a single object array.

Usage

From source file:com.google.code.nanorm.internal.introspect.asm.MapperBuilder.java

License:Apache License

/**
 * Generate mapper method.//from   w  w  w .  j  av a2s . c o m
 * 
 * @param owner self type
 * @param cw class writer
 * @param config method configuration
 */
private static void visitMethod(Type owner, ClassWriter cw, MethodConfig config) {
    java.lang.reflect.Method ifaceMethod = config.getMethod();
    Type returnType = Type.getType(ifaceMethod.getReturnType());
    Type[] args = new Type[ifaceMethod.getParameterTypes().length];
    for (int i = 0; i < args.length; ++i) {
        args[i] = Type.getType(ifaceMethod.getParameterTypes()[i]);
    }

    Method method = new Method(ifaceMethod.getName(), returnType, args);

    GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, method, null, null, cw);

    // Factory
    mg.loadThis();
    mg.getField(owner, "delegate", QUERY_DELEGATE_TYPE);

    // Statement config
    mg.loadThis();
    mg.getField(owner, "configs", STATEMENT_CONFIGS_ARR_TYPE);
    mg.push(config.getIndex());
    mg.arrayLoad(Type.getType(StatementConfig.class));

    // Arguments
    mg.loadArgArray();

    mg.invokeInterface(QUERY_DELEGATE_TYPE, QUERY_METHOD);
    mg.unbox(returnType);
    mg.returnValue();
    mg.endMethod();

    // Copy the annotations
    copyAnnotations(ifaceMethod, null, mg);
}

From source file:org.apache.aries.proxy.impl.gen.ProxySubclassAdapter.java

License:Apache License

private void processMethod(int access, String name, String desc, String signature, String[] exceptions) {
    LOGGER.debug(Constants.LOG_ENTRY, "processMethod",
            new Object[] { access, name, desc, signature, exceptions });

    LOGGER.debug("Processing method: {} with descriptor {}", name, desc);

    // identify the target method parameters and return type
    Method currentTransformMethod = new Method(name, desc);
    Type[] targetMethodParameters = currentTransformMethod.getArgumentTypes();
    Type returnType = currentTransformMethod.getReturnType();

    // we create a static field for each method we encounter with a name
    // like method_parm1_parm2...
    StringBuilder methodStaticFieldNameBuilder = new StringBuilder(name);
    // for each a parameter get the name and add it to the field removing
    // the dots first
    for (Type t : targetMethodParameters) {
        methodStaticFieldNameBuilder.append("_");
        methodStaticFieldNameBuilder//from   w  ww  .j  a v a2  s . c om
                .append(t.getClassName().replaceAll("\\[\\]", "Array").replaceAll("\\.", ""));
    }
    String methodStaticFieldName = methodStaticFieldNameBuilder.toString();

    // add a private static field for the method
    cv.visitField(ACC_PRIVATE | ACC_STATIC, methodStaticFieldName, METHOD_TYPE.getDescriptor(), null, null);

    // visit the method using the class writer, delegated through the method
    // visitor and generator
    // modify the method access so that any native methods aren't
    // described as native
    // since they won't be native in proxy form
    // also stop methods being marked synchronized on the proxy as they will
    // be sync
    // on the real object
    int newAccess = access & (~ACC_NATIVE) & (~ACC_SYNCHRONIZED);
    MethodVisitor mv = cv.visitMethod(newAccess, name, desc, signature, exceptions);
    // use a GeneratorAdapter to build the invoke call directly in byte code
    GeneratorAdapter methodAdapter = new GeneratorAdapter(mv, newAccess, name, desc);

    /*
     * Stage 1 creates the bytecode for adding the reflected method of the
     * superclass to a static field in the subclass: private static Method
     * methodName_parm1_parm2... = null; static{ methodName_parm1_parm2... =
     * superClass.getDeclaredMethod(methodName,new Class[]{method args}; }
     * 
     * Stage 2 is to call the ih.invoke(this,methodName_parm1_parm2,args) in
     * the new subclass methods Stage 3 is to cast the return value to the
     * correct type
     */

    /*
     * Stage 1 use superClass.getMethod(methodName,new Class[]{method args}
     * from the Class object on the stack
     */

    // load the static superclass Class onto the stack
    staticAdapter.getStatic(newClassType, currentClassFieldName, CLASS_TYPE);

    // push the method name string arg onto the stack
    staticAdapter.push(name);

    // create an array of the method parm class[] arg
    staticAdapter.push(targetMethodParameters.length);
    staticAdapter.newArray(CLASS_TYPE);
    int index = 0;
    for (Type t : targetMethodParameters) {
        staticAdapter.dup();
        staticAdapter.push(index);
        switch (t.getSort()) {
        case Type.BOOLEAN:
            staticAdapter.getStatic(Type.getType(java.lang.Boolean.class), "TYPE", CLASS_TYPE);
            break;
        case Type.BYTE:
            staticAdapter.getStatic(Type.getType(java.lang.Byte.class), "TYPE", CLASS_TYPE);
            break;
        case Type.CHAR:
            staticAdapter.getStatic(Type.getType(java.lang.Character.class), "TYPE", CLASS_TYPE);
            break;
        case Type.DOUBLE:
            staticAdapter.getStatic(Type.getType(java.lang.Double.class), "TYPE", CLASS_TYPE);
            break;
        case Type.FLOAT:
            staticAdapter.getStatic(Type.getType(java.lang.Float.class), "TYPE", CLASS_TYPE);
            break;
        case Type.INT:
            staticAdapter.getStatic(Type.getType(java.lang.Integer.class), "TYPE", CLASS_TYPE);
            break;
        case Type.LONG:
            staticAdapter.getStatic(Type.getType(java.lang.Long.class), "TYPE", CLASS_TYPE);
            break;
        case Type.SHORT:
            staticAdapter.getStatic(Type.getType(java.lang.Short.class), "TYPE", CLASS_TYPE);
            break;
        default:
        case Type.OBJECT:
            staticAdapter.push(t);
            break;
        }
        staticAdapter.arrayStore(CLASS_TYPE);
        index++;
    }

    // invoke the getMethod
    staticAdapter.invokeVirtual(CLASS_TYPE, new Method("getDeclaredMethod", METHOD_TYPE,
            new Type[] { STRING_TYPE, Type.getType(java.lang.Class[].class) }));

    // store the reflected method in the static field
    staticAdapter.putStatic(newClassType, methodStaticFieldName, METHOD_TYPE);

    /*
     * Stage 2 call the ih.invoke(this,supermethod,parms)
     */

    // load this to get the ih field
    methodAdapter.loadThis();
    // load the invocation handler from the field (the location of the
    // InvocationHandler.invoke)
    methodAdapter.getField(newClassType, IH_FIELD, IH_TYPE);
    // loadThis (the first arg of the InvocationHandler.invoke)
    methodAdapter.loadThis();
    // load the method to invoke (the second arg of the
    // InvocationHandler.invoke)
    methodAdapter.getStatic(newClassType, methodStaticFieldName, METHOD_TYPE);
    // load all the method arguments onto the stack as an object array (the
    // third arg of the InvocationHandler.invoke)
    methodAdapter.loadArgArray();
    // generate the invoke method
    Method invocationHandlerInvokeMethod = new Method("invoke", OBJECT_TYPE,
            new Type[] { OBJECT_TYPE, METHOD_TYPE, Type.getType(java.lang.Object[].class) });
    // call the invoke method of the invocation handler
    methodAdapter.invokeInterface(IH_TYPE, invocationHandlerInvokeMethod);

    /*
     * Stage 3 the returned object is now on the top of the stack We need to
     * check the type and cast as necessary
     */
    switch (returnType.getSort()) {
    case Type.BOOLEAN:
        methodAdapter.cast(OBJECT_TYPE, Type.getType(Boolean.class));
        methodAdapter.unbox(Type.BOOLEAN_TYPE);
        break;
    case Type.BYTE:
        methodAdapter.cast(OBJECT_TYPE, Type.getType(Byte.class));
        methodAdapter.unbox(Type.BYTE_TYPE);
        break;
    case Type.CHAR:
        methodAdapter.cast(OBJECT_TYPE, Type.getType(Character.class));
        methodAdapter.unbox(Type.CHAR_TYPE);
        break;
    case Type.DOUBLE:
        methodAdapter.cast(OBJECT_TYPE, Type.getType(Double.class));
        methodAdapter.unbox(Type.DOUBLE_TYPE);
        break;
    case Type.FLOAT:
        methodAdapter.cast(OBJECT_TYPE, Type.getType(Float.class));
        methodAdapter.unbox(Type.FLOAT_TYPE);
        break;
    case Type.INT:
        methodAdapter.cast(OBJECT_TYPE, Type.getType(Integer.class));
        methodAdapter.unbox(Type.INT_TYPE);
        break;
    case Type.LONG:
        methodAdapter.cast(OBJECT_TYPE, Type.getType(Long.class));
        methodAdapter.unbox(Type.LONG_TYPE);
        break;
    case Type.SHORT:
        methodAdapter.cast(OBJECT_TYPE, Type.getType(Short.class));
        methodAdapter.unbox(Type.SHORT_TYPE);
        break;
    case Type.VOID:
        methodAdapter.cast(OBJECT_TYPE, Type.getType(Void.class));
        methodAdapter.unbox(Type.VOID_TYPE);
        break;
    default:
    case Type.OBJECT:
        // in this case check the cast and cast the object to the return
        // type
        methodAdapter.checkCast(returnType);
        methodAdapter.cast(OBJECT_TYPE, returnType);
        break;
    }
    // return the (appropriately cast) result of the invocation from the
    // stack
    methodAdapter.returnValue();
    // end the method
    methodAdapter.endMethod();

    LOGGER.debug(Constants.LOG_EXIT, "processMethod");
}

From source file:org.apache.felix.ipojo.manipulation.ClassManipulator.java

License:Apache License

/**
 * Generate the method header of a POJO method.
 * This method header encapsulate the POJO method call to
 * signal entry exit and error to the container.
 * @param access : access flag./* w  ww  . ja v  a2s .c o m*/
 * @param name : method name.
 * @param desc : method descriptor.
 * @param signature : method signature.
 * @param exceptions : declared exceptions.
 * @param localVariables : the local variable nodes.
 * @param annotations : the annotations to move to this method.
 * @param paramAnnotations : the parameter annotations to move to this method.
 */
private void generateMethodHeader(int access, String name, String desc, String signature, String[] exceptions,
        List<LocalVariableNode> localVariables, List<AnnotationDescriptor> annotations,
        Map<Integer, List<AnnotationDescriptor>> paramAnnotations) {
    GeneratorAdapter mv = new GeneratorAdapter(cv.visitMethod(access, name, desc, signature, exceptions),
            access, name, desc);
    mv.visitCode();

    // If we have variables, we wraps the code within labels. The `lifetime` of the variables are bound to those
    // two variables.
    boolean hasArgumentLabels = localVariables != null && !localVariables.isEmpty();
    Label start = null;
    if (hasArgumentLabels) {
        start = new Label();
        mv.visitLabel(start);
    }

    mv.visitCode();

    Type returnType = Type.getReturnType(desc);

    // Compute result and exception stack location
    int result = -1;
    int exception;

    //int arguments = mv.newLocal(Type.getType((new Object[0]).getClass()));

    if (returnType.getSort() != Type.VOID) {
        // The method returns something
        result = mv.newLocal(returnType);
        exception = mv.newLocal(Type.getType(Throwable.class));
    } else {
        exception = mv.newLocal(Type.getType(Throwable.class));
    }

    Label l0 = new Label();
    Label l1 = new Label();
    Label l2 = new Label();

    mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Throwable");

    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, m_owner, generateMethodFlag(name, desc), "Z");
    mv.visitJumpInsn(IFNE, l0);

    mv.visitVarInsn(ALOAD, 0);
    mv.loadArgs();
    mv.visitMethodInsn(INVOKESPECIAL, m_owner, PREFIX + name, desc, false);
    mv.visitInsn(returnType.getOpcode(IRETURN));

    // end of the non intercepted method invocation.

    mv.visitLabel(l0);

    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, m_owner, IM_FIELD, "Lorg/apache/felix/ipojo/InstanceManager;");
    mv.visitVarInsn(ALOAD, 0);
    mv.visitLdcInsn(generateMethodId(name, desc));
    mv.loadArgArray();
    mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", ENTRY,
            "(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;)V", false);

    mv.visitVarInsn(ALOAD, 0);

    // Do not allow argument modification : just reload arguments.
    mv.loadArgs();
    mv.visitMethodInsn(INVOKESPECIAL, m_owner, PREFIX + name, desc, false);

    if (returnType.getSort() != Type.VOID) {
        mv.visitVarInsn(returnType.getOpcode(ISTORE), result);
    }

    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, m_owner, IM_FIELD, "Lorg/apache/felix/ipojo/InstanceManager;");
    mv.visitVarInsn(ALOAD, 0);
    mv.visitLdcInsn(generateMethodId(name, desc));
    if (returnType.getSort() != Type.VOID) {
        mv.visitVarInsn(returnType.getOpcode(ILOAD), result);
        mv.box(returnType);
    } else {
        mv.visitInsn(ACONST_NULL);
    }
    mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", EXIT,
            "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V", false);

    mv.visitLabel(l1);
    Label l7 = new Label();
    mv.visitJumpInsn(GOTO, l7);
    mv.visitLabel(l2);

    mv.visitVarInsn(ASTORE, exception);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, m_owner, IM_FIELD, "Lorg/apache/felix/ipojo/InstanceManager;");
    mv.visitVarInsn(ALOAD, 0);
    mv.visitLdcInsn(generateMethodId(name, desc));
    mv.visitVarInsn(ALOAD, exception);
    mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", ERROR,
            "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Throwable;)V", false);
    mv.visitVarInsn(ALOAD, exception);
    mv.visitInsn(ATHROW);

    mv.visitLabel(l7);
    if (returnType.getSort() != Type.VOID) {
        mv.visitVarInsn(returnType.getOpcode(ILOAD), result);
    }
    mv.visitInsn(returnType.getOpcode(IRETURN));

    // If we had arguments, we mark the end of the lifetime.
    Label end = null;
    if (hasArgumentLabels) {
        end = new Label();
        mv.visitLabel(end);
    }

    // Move annotations
    if (annotations != null) {
        for (AnnotationDescriptor ad : annotations) {
            ad.visitAnnotation(mv);
        }
    }

    // Move parameter annotations
    if (paramAnnotations != null && !paramAnnotations.isEmpty()) {
        for (Integer id : paramAnnotations.keySet()) {
            List<AnnotationDescriptor> ads = paramAnnotations.get(id);
            for (AnnotationDescriptor ad : ads) {
                ad.visitParameterAnnotation(id, mv);
            }
        }
    }

    // Write the arguments name.
    if (hasArgumentLabels) {
        for (LocalVariableNode var : localVariables) {
            mv.visitLocalVariable(var.name, var.desc, var.signature, start, end, var.index);
        }
    }

    mv.visitMaxs(0, 0);
    mv.visitEnd();
}

From source file:org.apache.felix.ipojo.manipulation.MethodCreator.java

License:Apache License

/**
 * Generate the method header of a POJO method.
 * This method header encapsulate the POJO method call to
 * signal entry exit and error to the container.
 * @param access : access flag./*  w w w  .j a v  a2 s  .c  om*/
 * @param name : method name.
 * @param desc : method descriptor.
 * @param signature : method signature.
 * @param exceptions : declared exceptions.
 * @param annotations : the annotations to move to this method.
 * @param paramAnnotations : the parameter annotations to move to this method.
 */
private void generateMethodHeader(int access, String name, String desc, String signature, String[] exceptions,
        List annotations, Map paramAnnotations) {
    GeneratorAdapter mv = new GeneratorAdapter(cv.visitMethod(access, name, desc, signature, exceptions),
            access, name, desc);

    mv.visitCode();

    Type returnType = Type.getReturnType(desc);

    // Compute result and exception stack location
    int result = -1;
    int exception = -1;

    //int arguments = mv.newLocal(Type.getType((new Object[0]).getClass()));

    if (returnType.getSort() != Type.VOID) {
        // The method returns something 
        result = mv.newLocal(returnType);
        exception = mv.newLocal(Type.getType(Throwable.class));
    } else {
        exception = mv.newLocal(Type.getType(Throwable.class));
    }

    Label l0 = new Label();
    Label l1 = new Label();
    Label l2 = new Label();

    mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Throwable");

    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, m_owner, generateMethodFlag(name, desc), "Z");
    mv.visitJumpInsn(IFNE, l0);

    mv.visitVarInsn(ALOAD, 0);
    mv.loadArgs();
    mv.visitMethodInsn(INVOKESPECIAL, m_owner, PREFIX + name, desc);
    mv.visitInsn(returnType.getOpcode(IRETURN));

    // end of the non intercepted method invocation.

    mv.visitLabel(l0);

    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, m_owner, IM_FIELD, "Lorg/apache/felix/ipojo/InstanceManager;");
    mv.visitVarInsn(ALOAD, 0);
    mv.visitLdcInsn(generateMethodId(name, desc));
    mv.loadArgArray();
    mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", ENTRY,
            "(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;)V");

    mv.visitVarInsn(ALOAD, 0);

    // Do not allow argument modification : just reload arguments.
    mv.loadArgs();
    mv.visitMethodInsn(INVOKESPECIAL, m_owner, PREFIX + name, desc);

    if (returnType.getSort() != Type.VOID) {
        mv.visitVarInsn(returnType.getOpcode(ISTORE), result);
    }

    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, m_owner, IM_FIELD, "Lorg/apache/felix/ipojo/InstanceManager;");
    mv.visitVarInsn(ALOAD, 0);
    mv.visitLdcInsn(generateMethodId(name, desc));
    if (returnType.getSort() != Type.VOID) {
        mv.visitVarInsn(returnType.getOpcode(ILOAD), result);
        mv.box(returnType);
    } else {
        mv.visitInsn(ACONST_NULL);
    }
    mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", EXIT,
            "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V");

    mv.visitLabel(l1);
    Label l7 = new Label();
    mv.visitJumpInsn(GOTO, l7);
    mv.visitLabel(l2);

    mv.visitVarInsn(ASTORE, exception);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, m_owner, IM_FIELD, "Lorg/apache/felix/ipojo/InstanceManager;");
    mv.visitVarInsn(ALOAD, 0);
    mv.visitLdcInsn(generateMethodId(name, desc));
    mv.visitVarInsn(ALOAD, exception);
    mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", ERROR,
            "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Throwable;)V");
    mv.visitVarInsn(ALOAD, exception);
    mv.visitInsn(ATHROW);

    mv.visitLabel(l7);
    if (returnType.getSort() != Type.VOID) {
        mv.visitVarInsn(returnType.getOpcode(ILOAD), result);
    }
    mv.visitInsn(returnType.getOpcode(IRETURN));

    // Move annotations
    if (annotations != null) {
        for (int i = 0; i < annotations.size(); i++) {
            AnnotationDescriptor ad = (AnnotationDescriptor) annotations.get(i);
            ad.visitAnnotation(mv);
        }
    }

    // Move parameter annotations
    if (paramAnnotations != null && !paramAnnotations.isEmpty()) {
        Iterator ids = paramAnnotations.keySet().iterator();
        while (ids.hasNext()) {
            Integer id = (Integer) ids.next();
            List ads = (List) paramAnnotations.get(id);
            for (int i = 0; i < ads.size(); i++) {
                AnnotationDescriptor ad = (AnnotationDescriptor) ads.get(i);
                ad.visitParameterAnnotation(id.intValue(), mv);
            }
        }
    }

    mv.visitMaxs(0, 0);
    mv.visitEnd();
}

From source file:org.evosuite.stubs.StubClassVisitor.java

License:Open Source License

/**
 * Stubbed methods forward the query to the central Stubs class
 * and return whatever that class tells it to return
 * /*from  ww w .  j a  va  2s.co  m*/
 * @param mg
 * @param m
 */
private void createMethod(GeneratorAdapter mg, Method m) {
    String methodName = "getReturnValue" + getTypeName(m.getReturnType());
    String desc = "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)"
            + getReturnTypeDesc(m.getReturnType());
    mg.push(className);
    mg.push(m.getName() + m.getDescriptor());
    mg.loadArgArray();
    Type owner = Type.getType(PackageInfo.getNameWithSlash(Stubs.class));
    Method method = new Method(methodName, desc);
    mg.invokeStatic(owner, method);
    insertReturnCast(mg, m);
    mg.returnValue();
    mg.endMethod();
}

From source file:org.jruby.javasupport.proxy.JavaProxyClassFactory.java

License:LGPL

private static void generateProxyMethod(Type selfType, Type superType, ClassVisitor cw,
        GeneratorAdapter clazzInit, MethodData md) {
    if (!md.generateProxyMethod()) {
        return;/*www  .  ja v a 2  s. c o  m*/
    }

    org.objectweb.asm.commons.Method m = md.getMethod();
    Type[] ex = toType(md.getExceptions());

    String field_name = "__mth$" + md.getName() + md.scrambledSignature();

    // create static private method field
    FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, field_name,
            PROXY_METHOD_TYPE.getDescriptor(), null, null);
    fv.visitEnd();

    clazzInit.dup();
    clazzInit.push(m.getName());
    clazzInit.push(m.getDescriptor());
    clazzInit.push(md.isImplemented());
    clazzInit.invokeStatic(PROXY_HELPER_TYPE, PROXY_HELPER_GET_METHOD);
    clazzInit.putStatic(selfType, field_name, PROXY_METHOD_TYPE);

    org.objectweb.asm.commons.Method sm = new org.objectweb.asm.commons.Method("__super$" + m.getName(),
            m.getReturnType(), m.getArgumentTypes());

    //
    // construct the proxy method
    //
    GeneratorAdapter ga = new GeneratorAdapter(Opcodes.ACC_PUBLIC, m, null, ex, cw);

    ga.loadThis();
    ga.getField(selfType, INVOCATION_HANDLER_FIELD_NAME, INVOCATION_HANDLER_TYPE);

    // if the method is extending something, then we have
    // to test if the handler is initialized...

    if (md.isImplemented()) {
        ga.dup();
        Label ok = ga.newLabel();
        ga.ifNonNull(ok);

        ga.loadThis();
        ga.loadArgs();
        ga.invokeConstructor(superType, m);
        ga.returnValue();
        ga.mark(ok);
    }

    ga.loadThis();
    ga.getStatic(selfType, field_name, PROXY_METHOD_TYPE);

    if (m.getArgumentTypes().length == 0) {
        // load static empty array
        ga.getStatic(JAVA_PROXY_TYPE, "NO_ARGS", Type.getType(Object[].class));
    } else {
        // box arguments
        ga.loadArgArray();
    }

    Label before = ga.mark();

    ga.invokeInterface(INVOCATION_HANDLER_TYPE, INVOCATION_HANDLER_INVOKE_METHOD);

    Label after = ga.mark();

    ga.unbox(m.getReturnType());
    ga.returnValue();

    // this is a simple rethrow handler
    Label rethrow = ga.mark();
    ga.visitInsn(Opcodes.ATHROW);

    for (int i = 0; i < ex.length; i++) {
        ga.visitTryCatchBlock(before, after, rethrow, ex[i].getInternalName());
    }

    ga.visitTryCatchBlock(before, after, rethrow, "java/lang/Error");
    ga.visitTryCatchBlock(before, after, rethrow, "java/lang/RuntimeException");

    Type thr = Type.getType(Throwable.class);
    Label handler = ga.mark();
    Type udt = Type.getType(UndeclaredThrowableException.class);
    int loc = ga.newLocal(thr);
    ga.storeLocal(loc, thr);
    ga.newInstance(udt);
    ga.dup();
    ga.loadLocal(loc, thr);
    ga.invokeConstructor(udt, org.objectweb.asm.commons.Method.getMethod("void <init>(java.lang.Throwable)"));
    ga.throwException();

    ga.visitTryCatchBlock(before, after, handler, "java/lang/Throwable");

    ga.endMethod();

    //
    // construct the super-proxy method
    //
    if (md.isImplemented()) {

        GeneratorAdapter ga2 = new GeneratorAdapter(Opcodes.ACC_PUBLIC, sm, null, ex, cw);

        ga2.loadThis();
        ga2.loadArgs();
        ga2.invokeConstructor(superType, m);
        ga2.returnValue();
        ga2.endMethod();
    }
}