Example usage for org.objectweb.asm.commons Method Method

List of usage examples for org.objectweb.asm.commons Method Method

Introduction

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

Prototype

public Method(final String name, final String descriptor) 

Source Link

Document

Constructs a new Method .

Usage

From source file:nl.hardijzer.fw.checkabstract.ClassInfo.java

License:Open Source License

public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
    Method m = new Method(name, desc);
    boolean bAbstract = ((access & Opcodes.ACC_ABSTRACT) != 0);
    if (bAbstract)
        info.setAbstractMethods.add(m);//from ww w.  ja  va  2s.  co  m
    else
        info.setMethods.add(m);
    info.mapMethodOwner.put(m, info.strName);
    return super.visitMethod(access, name, desc, signature, exceptions);
}

From source file:org.apache.aries.proxy.impl.common.AbstractWovenProxyAdapter.java

License:Apache License

/**
 * This method is called on each method implemented on this object (but not
 * for superclass methods) Each of these methods is visited in turn and the
 * code here generates the byte code for the calls to the InovcationListener
 * around the existing method//  w  ww .jav  a 2s .c  o  m
 */
public final MethodVisitor visitMethod(int access, String name, String desc, String signature,
        String[] exceptions) {
    LOGGER.debug(Constants.LOG_ENTRY, "visitMethod",
            new Object[] { access, name, desc, signature, exceptions });

    Method currentMethod = new Method(name, desc);

    getKnownMethods().add(currentMethod);

    MethodVisitor methodVisitorToReturn = null;

    // Only weave "real" instance methods. Not constructors, initializers or
    // compiler generated ones.
    if ((access & (ACC_STATIC | ACC_PRIVATE | ACC_SYNTHETIC | ACC_NATIVE | ACC_BRIDGE)) == 0
            && !!!name.equals("<init>") && !!!name.equals("<clinit>")) {

        // found a method we should weave

        //Create a field name and store it for later
        String methodStaticFieldName = "methodField" + getSanitizedUUIDString();
        transformedMethods.put(methodStaticFieldName,
                new TypeMethod(currentMethodDeclaringType, currentMethod));

        // Surround the MethodVisitor with our weaver so we can manipulate the code
        methodVisitorToReturn = getWeavingMethodVisitor(access, name, desc, signature, exceptions,
                currentMethod, methodStaticFieldName, currentMethodDeclaringType,
                currentMethodDeclaringTypeIsInterface);
    } else if (name.equals("<clinit>")) {
        //there is an existing clinit method, change the fields we use
        //to write our init code to static_init_UUID instead
        staticInitMethod = new Method("static_init_" + UU_ID, Type.VOID_TYPE, NO_ARGS);
        staticInitMethodFlags = staticInitMethodFlags | ACC_FINAL;
        methodVisitorToReturn = new AdviceAdapter(Opcodes.ASM5,
                cv.visitMethod(access, name, desc, signature, exceptions), access, name, desc) {
            @Override
            protected void onMethodEnter() {
                //add into the <clinit> a call to our synthetic static_init_UUID
                invokeStatic(typeBeingWoven, staticInitMethod);
                super.onMethodEnter();
            }
        };
    } else {
        if (currentMethod.getArgumentTypes().length == 0 && name.equals("<init>"))
            hasNoArgsConstructor = true;
        //This isn't a method we want to weave, so just get the default visitor
        methodVisitorToReturn = cv.visitMethod(access, name, desc, signature, exceptions);
    }

    LOGGER.debug(Constants.LOG_EXIT, "visitMethod", methodVisitorToReturn);
    return methodVisitorToReturn;
}

From source file:org.apache.aries.proxy.impl.common.MethodCopyingClassAdapter.java

License:Apache License

@Override
public final MethodVisitor visitMethod(final int access, String name, String desc, String sig,
        String[] exceptions) {/* ww w.j  ava2  s  .  co m*/

    MethodVisitor mv = null;
    //As in WovenProxyAdapter, we only care about "real" methods, but also not
    //abstract ones!.
    if (!!!name.equals("<init>") && !!!name.equals("<clinit>") && (access
            & (ACC_STATIC | ACC_PRIVATE | ACC_SYNTHETIC | ACC_ABSTRACT | ACC_NATIVE | ACC_BRIDGE)) == 0) {

        // identify the target method parameters and return type
        Method currentTransformMethod = new Method(name, desc);
        // We don't want to duplicate a method we already overrode! 
        if (!!!knownMethods.add(currentTransformMethod))
            return null;

        // found a method we should weave
        // We can't override a final method
        if ((access & ACC_FINAL) != 0)
            throw new RuntimeException(new FinalModifierException(superToCopy, name));
        // We can't call up to a default access method if we aren't in the same
        // package
        if ((access & (ACC_PUBLIC | ACC_PROTECTED | ACC_PRIVATE)) == 0) {
            if (!!!samePackage)
                throw new RuntimeException(NLS.MESSAGES.getMessage("method.from.superclass.is.hidden", name,
                        superToCopy.getName(), overridingClassType.getClassName()),
                        new UnableToProxyException(superToCopy));
        }
        //Safe to copy a call to this method!
        Type superType = Type.getType(superToCopy);

        // identify the target method parameters and return type
        String methodStaticFieldName = "methodField" + AbstractWovenProxyAdapter.getSanitizedUUIDString();
        transformedMethods.put(methodStaticFieldName, new TypeMethod(superType, currentTransformMethod));

        //Remember we need to copy the fake method *and* weave it, use a 
        //WovenProxyMethodAdapter as well as a CopyingMethodAdapter

        MethodVisitor weaver = wovenProxyAdapter.getWeavingMethodVisitor(access, name, desc, sig, exceptions,
                currentTransformMethod, methodStaticFieldName, superType, false);

        if (weaver instanceof AbstractWovenProxyMethodAdapter) {
            //If we are weaving this method then we might have a problem. If it's a protected method and we
            //aren't in the same package then we can't dispatch the call to another object. This may sound
            //odd, but if class Super has a protected method foo(), then class Sub, that extends Super, cannot
            //call ((Super)o).foo() in code (it can call super.foo()). If we are in the same package then this
            //gets around the problem, but if not the class will fail verification.
            if (!samePackage && (access & ACC_PROTECTED) != 0)
                throw new RuntimeException(NLS.MESSAGES.getMessage("method.from.superclass.is.hidden", name,
                        superToCopy.getName(), overridingClassType.getClassName()),
                        new UnableToProxyException(superToCopy));
            mv = new CopyingMethodAdapter((GeneratorAdapter) weaver, superType, currentTransformMethod);
        } else {
            //For whatever reason we aren't weaving this method. The call to super.xxx() will always work
            mv = new CopyingMethodAdapter(new GeneratorAdapter(access, currentTransformMethod, mv), superType,
                    currentTransformMethod);
        }
    }

    return mv;
}

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   ww  w . java  2s. c o  m*/
                .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.aries.proxy.impl.interfaces.InterfaceCombiningClassAdapter.java

License:Apache License

@Override
public final MethodVisitor visitMethod(int access, String name, String desc, String sig, String[] arg4) {
    //If we already implement this method (from another interface) then we don't
    //want a duplicate. We also don't want to copy any static init blocks (these
    //initialize static fields on the interface that we don't copy
    if (adapter.getKnownMethods().contains(new Method(name, desc)) || "<clinit>".equals(name)) {
        return null;
    } else if (((access & (ACC_PRIVATE | ACC_SYNTHETIC)) == (ACC_PRIVATE | ACC_SYNTHETIC))) {
        // private, synthetic methods on interfaces don't need to be proxied.       
        return null;
    } else {//We're going to implement this method, so make it non abstract!
        return adapter.visitMethod(access, name, desc, null, arg4);
    }//from w  w w  . j  av  a2 s. c  o m
}

From source file:org.apache.commons.weaver.normalizer.Normalizer.java

License:Apache License

/**
 * Create the normalized version of a given class in the configured target package. The {@link Normalizer} will
 * gladly do so in a package from which the normalized class will not actually be able to reference any types upon
 * which it relies; in such a situation you must specify the target package as the package of the supertype.
 * @param key used to generate the normalized classname.
 * @param classWrapper/*from   w w  w.ja v a  2 s .c om*/
 * @return the generated classname.
 * @throws IOException
 */
private String copy(final Pair<String, String> key, final ClassWrapper classWrapper) throws IOException {
    env.debug("Copying %s to %s", key, targetPackage);
    final MessageDigest md5;
    try {
        md5 = MessageDigest.getInstance("MD5");
    } catch (final NoSuchAlgorithmException e) {
        throw new IllegalStateException(e);
    }
    md5.update(key.getLeft().getBytes(StandardCharsets.UTF_8));
    md5.update(key.getRight().getBytes(StandardCharsets.UTF_8));

    final long digest = Conversion.byteArrayToLong(md5.digest(), 0, 0L, 0, Long.SIZE / Byte.SIZE);

    final String result = MessageFormat.format("{0}/$normalized{1,number,0;_0}", targetPackage, digest);

    env.debug("Copying class %s to %s", classWrapper.wrapped.getName(), result);

    try (InputStream bytecode = env.getClassfile(classWrapper.wrapped).getInputStream()) {
        final ClassReader reader = new ClassReader(bytecode);
        final ClassVisitor writeClass = new WriteClass();

        // we're doing most of this by hand; we only read the original class to hijack signature, ctor exceptions,
        // etc.:

        reader.accept(new ClassVisitor(ASM_VERSION) {
            Type supertype;

            @Override
            @SuppressWarnings("PMD.UseVarargs") //overridden method
            public void visit(final int version, final int access, final String name, final String signature,
                    final String superName, final String[] interfaces) {
                supertype = Type.getObjectType(superName);
                writeClass.visit(version, Opcodes.ACC_PUBLIC, result, signature, superName, interfaces);
                visitAnnotation(Type.getType(Marker.class).getDescriptor(), false);
            }

            @Override
            @SuppressWarnings("PMD.UseVarargs") //overridden method
            public MethodVisitor visitMethod(final int access, final String name, final String desc,
                    final String signature, final String[] exceptions) {
                if (INIT.equals(name)) {
                    final Method staticCtor = new Method(INIT, key.getRight());
                    final Type[] argumentTypes = staticCtor.getArgumentTypes();
                    final Type[] exceptionTypes = toObjectTypes(exceptions);

                    {
                        final GeneratorAdapter mgen = new GeneratorAdapter(Opcodes.ACC_PUBLIC, staticCtor,
                                signature, exceptionTypes, writeClass);
                        mgen.visitCode();
                        mgen.loadThis();
                        for (int i = 0; i < argumentTypes.length; i++) {
                            mgen.loadArg(i);
                        }
                        mgen.invokeConstructor(supertype, staticCtor);
                        mgen.returnValue();
                        mgen.endMethod();
                    }
                    /*
                     * now declare a dummy constructor that will match, and discard,
                     * any originally inner-class bound constructor i.e. that set up a this$0 field.
                     * By doing this we can avoid playing with the stack that originally
                     * invoked such a constructor and simply rewrite the method
                     */
                    {
                        final Method instanceCtor = new Method(INIT, Type.VOID_TYPE,
                                ArrayUtils.insert(0, argumentTypes, OBJECT_TYPE));
                        final GeneratorAdapter mgen = new GeneratorAdapter(Opcodes.ACC_PUBLIC, instanceCtor,
                                signature, exceptionTypes, writeClass);
                        mgen.visitCode();
                        mgen.loadThis();
                        for (int i = 0; i < argumentTypes.length; i++) {
                            mgen.loadArg(i + 1);
                        }
                        mgen.invokeConstructor(supertype, staticCtor);
                        mgen.returnValue();
                        mgen.endMethod();
                    }
                    return null;
                }
                return null;
            }

            @Override
            public void visitEnd() {
                writeClass.visitEnd();
            }
        }, 0);
    }
    return result;
}

From source file:org.apache.commons.weaver.privilizer.ActionGenerator.java

License:Apache License

/**
 * Create a new {@link ActionGenerator}.
 * @param access modifier//w  w w . ja v a2 s  .c  om
 * @param methd {@link Method} to implement
 * @param exceptions thrown
 * @param owner of the action class
 */
ActionGenerator(final int access, final Method methd, final String[] exceptions,
        final PrivilizingVisitor owner) {
    owner.privilizer().super(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
    this.methd = methd;
    this.exc = ArrayUtils.isNotEmpty(exceptions);
    this.exceptions = exc ? new Type[] { Type.getType(Exception.class) } : null;
    this.owner = owner;
    this.simpleName = generateName(methd);
    this.action = Type.getObjectType(owner.className + '$' + simpleName);

    int privilegedAccessIndex = -1;
    String implName = null;
    for (final Map.Entry<Method, String> entry : owner.privilegedMethods.entrySet()) {
        privilegedAccessIndex++;
        if (entry.getKey().equals(methd)) {
            implName = entry.getValue();
            break;
        }
    }
    Validate.validState(implName != null);

    this.index = privilegedAccessIndex;

    this.impl = new Method(implName, methd.getDescriptor());
    this.implIsStatic = Modifier.isStatic(access);
    final Type[] args = implIsStatic ? methd.getArgumentTypes()
            : ArrayUtils.insert(0, methd.getArgumentTypes(), owner.target);
    this.helper = new Method(privilizer().generateName("access$" + index), methd.getReturnType(), args);
    this.result = Privilizer.wrap(methd.getReturnType());
    this.fields = fields(args);
    this.actionInterface = Type.getType(exc ? PrivilegedExceptionAction.class : PrivilegedAction.class);
}

From source file:org.apache.commons.weaver.privilizer.BlueprintingVisitor.java

License:Apache License

private static Pair<Type, Method> methodKey(String owner, String name, String desc) {
    return Pair.of(Type.getObjectType(owner), new Method(name, desc));
}

From source file:org.apache.commons.weaver.privilizer.BlueprintingVisitor.java

License:Apache License

private TypeInfo typeInfo(Type type) {
    return typeInfoCache.computeIfAbsent(type, k -> {
        final ClassNode cn = read(k.getClassName());

        return new TypeInfo(cn.access, cn.superName,
                cn.fields.stream().collect(Collectors.toMap(f -> f.name, Function.identity())),
                cn.methods.stream()//from   w  w  w. j  a v  a  2  s .  c o m
                        .collect(Collectors.toMap(m -> new Method(m.name, m.desc), Function.identity())));
    });
}

From source file:org.apache.commons.weaver.privilizer.PrivilizingVisitor.java

License:Apache License

@Override
@SuppressWarnings("PMD.UseVarargs") //overridden method
public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature,
        final String[] exceptions) {
    annotate();/*from  ww  w  .j  a  v  a 2s  . com*/
    final MethodVisitor originalMethod = super.visitMethod(access, name, desc, signature, exceptions);
    final Method methd = new Method(name, desc);

    return new GeneratorAdapter(Privilizer.ASM_VERSION, originalMethod, access, name, desc) {

        @Override
        public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
            if (Type.getType(Privileged.class).getDescriptor().equals(desc)) {
                final AccessLevel localAccessLevel = AccessLevel.of(access);
                if (accessLevel.compareTo(localAccessLevel) > 0) {
                    throw new IllegalStateException(new IllegalAccessException(
                            "Method " + className + "#" + methd + " must have maximum access level '"
                                    + accessLevel + "' but is defined wider ('" + localAccessLevel + "')"));
                }
                if (AccessLevel.PACKAGE.compareTo(accessLevel) > 0) {
                    privilizer().env.warn("Possible security leak: granting privileges to %s method %s.%s",
                            localAccessLevel, className, methd);
                }
                privilegedMethods.put(methd, privilizer().generateName(name));
            }
            return super.visitAnnotation(desc, visible);
        }

        @Override
        public void visitCode() {
            super.visitCode();
            if (!privilegedMethods.containsKey(methd)) {
                return;
            }
            final String impl = privilegedMethods.get(methd);
            final boolean instanceMethod = !Modifier.isStatic(access);

            if (policy.isConditional()) {
                privilizer().env.debug("setting up conditional execution due to policy %s", policy);
                // test, loading boolean
                if (policy == Policy.ON_INIT) {
                    getStatic(target, privilizer().generateName("hasSecurityManager"), Type.BOOLEAN_TYPE);
                } else if (policy == Policy.DYNAMIC) {
                    checkSecurityManager(this);
                }
                final Label doPrivileged = new Label();

                // if true, goto doPrivileged:
                ifZCmp(NE, doPrivileged);

                final Method implMethod = new Method(impl, desc);
                if (instanceMethod) {
                    loadThis();
                    loadArgs();
                    invokeVirtual(target, implMethod);
                } else {
                    loadArgs();
                    invokeStatic(target, implMethod);
                }
                returnValue();
                mark(doPrivileged);
            } else {
                privilizer().env.debug("setting up unconditional privileged execution due to policy %s",
                        policy);
            }
            // generate action:
            final Type[] ctorArgs = instanceMethod ? ArrayUtils.insert(0, methd.getArgumentTypes(), target)
                    : methd.getArgumentTypes();
            final Type actionType = new ActionGenerator(access, methd, exceptions, PrivilizingVisitor.this)
                    .build();
            newInstance(actionType);
            dup();
            if (instanceMethod) {
                loadThis();
            }
            loadArgs();
            invokeConstructor(actionType, new Method("<init>", Type.VOID_TYPE, ctorArgs));

            final boolean exc = ArrayUtils.isNotEmpty(exceptions);
            // mark try if needed
            final Label privTry = exc ? mark() : null;

            // execute action
            final Type arg = exc ? Type.getType(PrivilegedExceptionAction.class)
                    : Type.getType(PrivilegedAction.class);
            final Method doPrivileged = new Method("doPrivileged", Type.getType(Object.class),
                    new Type[] { arg });
            invokeStatic(Type.getType(AccessController.class), doPrivileged);

            unbox(methd.getReturnType());
            returnValue();

            if (exc) {
                final Type caught = Type.getType(PrivilegedActionException.class);
                // end try
                final Label privCatch = mark();
                // catch
                catchException(privTry, privCatch, caught);
                // unwrap
                invokeVirtual(caught,
                        new Method("getException", Type.getType(Exception.class), Privilizer.EMPTY_TYPE_ARRAY));
                // throw
                throwException();
            }
            // end original method
            endMethod();

            // substitute an impl visitor and continue
            mv = cv.visitMethod(AccessLevel.PRIVATE.merge(access), impl, desc, signature, exceptions);
            mv.visitCode();
        }
    };
}