Java Code Examples for org.apache.bcel.generic.INVOKEVIRTUAL

The following examples show how to use org.apache.bcel.generic.INVOKEVIRTUAL. These examples are extracted from open source projects. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
public boolean preScreen(MethodGen mg) {
    ConstantPoolGen cpg = mg.getConstantPool();

    int lockCount = mg.isSynchronized() ? 1 : 0;
    boolean sawWaitOrNotify = false;

    InstructionHandle handle = mg.getInstructionList().getStart();
    while (handle != null && !(lockCount >= 2 && sawWaitOrNotify)) {
        Instruction ins = handle.getInstruction();
        if (ins instanceof MONITORENTER) {
            ++lockCount;
        } else if (ins instanceof INVOKEVIRTUAL) {
            INVOKEVIRTUAL inv = (INVOKEVIRTUAL) ins;
            String methodName = inv.getMethodName(cpg);
            if ("wait".equals(methodName) || methodName.startsWith("notify")) {
                sawWaitOrNotify = true;
            }
        }

        handle = handle.getNext();
    }

    return lockCount >= 2 && sawWaitOrNotify;
}
 
Example 2
@Override
public void visitINVOKEVIRTUAL(INVOKEVIRTUAL obj) {

    if ("cast".equals(obj.getMethodName(cpg)) && "java.lang.Class".equals(obj.getClassName(cpg))) {
        // treat as no-op
        try {
            ValueNumberFrame frame = getFrame();
            ValueNumber resultType = frame.popValue();
            frame.popValue();
            frame.pushValue(resultType);
        } catch (DataflowAnalysisException e) {
            AnalysisContext.logError("oops", e);
        }
        return;
    }
    handleNormalInstruction(obj);
}
 
Example 3
Source Project: commons-bcel   Source File: Pass3aVerifier.java    License: Apache License 2.0 6 votes vote down vote up
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
@Override
public void visitINVOKEVIRTUAL(final INVOKEVIRTUAL o) {
    try {
    // INVOKEVIRTUAL is a LoadClass; the Class where the referenced method is declared in,
    // is therefore resolved/verified.
    // INVOKEVIRTUAL is an InvokeInstruction, the argument and return types are resolved/verified,
    // too. So are the allowed method names.
    final String classname = o.getClassName(constantPoolGen);
    final JavaClass jc = Repository.lookupClass(classname);
    final Method m = getMethodRecursive(jc, o);
    if (m == null) {
        constraintViolated(o, "Referenced method '"+o.getMethodName(constantPoolGen)+"' with expected signature '"+
            o.getSignature(constantPoolGen)+"' not found in class '"+jc.getClassName()+"'.");
    }
    if (! (jc.isClass())) {
        constraintViolated(o, "Referenced class '"+jc.getClassName()+"' is an interface, but not a class as expected.");
    }

    } catch (final ClassNotFoundException e) {
    // FIXME: maybe not the best way to handle this
    throw new AssertionViolatedException("Missing class: " + e, e);
    }
}
 
Example 4
private void analyzeMethod(Method m, ClassContext classContext) throws CFGBuilderException{
    JavaClass clazz = classContext.getJavaClass();
    ConstantPoolGen cpg = classContext.getConstantPoolGen();
    CFG cfg = classContext.getCFG(m);

    for (Iterator<Location> i = cfg.locationIterator(); i.hasNext(); ) {
        Location loc = i.next();
        Instruction inst = loc.getHandle().getInstruction();

        if (inst instanceof INVOKEVIRTUAL) {
            INVOKEVIRTUAL invoke = (INVOKEVIRTUAL)inst;
            if( "java.lang.StringBuilder".equals(invoke.getClassName(cpg)) && "append".equals(invoke.getMethodName(cpg))) {
                Instruction prev = loc.getHandle().getPrev().getInstruction();

                if (prev instanceof LDC) {
                    LDC ldc = (LDC)prev;
                    Object value = ldc.getValue(cpg);

                    if (value instanceof String) {
                        String v = (String)value;

                        if ("redirect:".equals(v)) {
                            BugInstance bug = new BugInstance(this, SPRING_UNVALIDATED_REDIRECT_TYPE, Priorities.NORMAL_PRIORITY);
                            bug.addClass(clazz).addMethod(clazz,m).addSourceLine(classContext,m,loc);
                            reporter.reportBug(bug);
                        }
                    }
                }
            }
        }
    }
}
 
Example 5
/**
 * This method is used to track calls made on a specific object. For instance, this could be used to track if "setHttpOnly(true)"
 * was executed on a specific cookie object.
 *
 * This allows the detector to find interchanged calls like this
 *
 * Cookie cookie1 = new Cookie("f", "foo");     <- This cookie is unsafe
 * Cookie cookie2 = new Cookie("b", "bar");     <- This cookie is safe
 * cookie1.setHttpOnly(false);
 * cookie2.setHttpOnly(true);
 *
 * @param cpg ConstantPoolGen
 * @param startLocation The Location of the cookie initialization call.
 * @param objectStackLocation The index of the cookie on the stack.
 * @param invokeInstruction The instruction we want to detect.s
 * @return The location of the invoke instruction provided for the cookie at a specific index on the stack.
 */
private Location getCookieInstructionLocation(ConstantPoolGen cpg, Location startLocation, int objectStackLocation, String invokeInstruction) {
    Location location = startLocation;
    InstructionHandle handle = location.getHandle();

    int loadedStackValue = 0;

    // Loop until we find the setSecure call for this cookie
    while (handle.getNext() != null) {
        handle = handle.getNext();
        Instruction nextInst = handle.getInstruction();

        // We check if the index of the cookie used for this invoke is the same as the one provided
        if (nextInst instanceof ALOAD) {
            ALOAD loadInst = (ALOAD)nextInst;
            loadedStackValue = loadInst.getIndex();
        }

        if (nextInst instanceof INVOKEVIRTUAL
                && loadedStackValue == objectStackLocation) {
            INVOKEVIRTUAL invoke = (INVOKEVIRTUAL) nextInst;

            String methodNameWithSignature = invoke.getClassName(cpg) + "." + invoke.getMethodName(cpg);

            if (methodNameWithSignature.equals(invokeInstruction)) {

                Integer val = ByteCode.getConstantInt(handle.getPrev());

                if (val != null && val == TRUE_INT_VALUE) {
                    return new Location(handle, location.getBasicBlock());
                }
            }
        }
    }

    return null;
}
 
Example 6
private Map<String, List<Location>> get_line_location(Method m, ClassContext classContext){
        HashMap<String, List<Location>> all_line_location = new HashMap<>();
        ConstantPoolGen cpg = classContext.getConstantPoolGen();
        CFG cfg = null;
        try {
            cfg = classContext.getCFG(m);
        } catch (CFGBuilderException e) {
            e.printStackTrace();
            return all_line_location;
        }
        for (Iterator<Location> i = cfg.locationIterator(); i.hasNext(); ) {
            Location loc = i.next();
            Instruction inst = loc.getHandle().getInstruction();
            if(inst instanceof INVOKEVIRTUAL) {
                INVOKEVIRTUAL invoke = (INVOKEVIRTUAL) inst;
//                if (classname.equals(invoke.getClassName(cpg)) &&
//                        methodName.equals(invoke.getMethodName(cpg))) {
                    if(all_line_location.containsKey(invoke.getMethodName(cpg))){
                        all_line_location.get(invoke.getMethodName(cpg)).add(loc);
                    }else {
                        LinkedList<Location> loc_list = new LinkedList<>();
                        loc_list.add(loc);
                        all_line_location.put(invoke.getMethodName(cpg), loc_list);
                    }
//                }
            }
        }
        return all_line_location;
    }
 
Example 7
Source Project: spotbugs   Source File: Stream.java    License: GNU Lesser General Public License v2.1 5 votes vote down vote up
public boolean isStreamClose(BasicBlock basicBlock, InstructionHandle handle, ConstantPoolGen cpg, ResourceValueFrame frame,
        RepositoryLookupFailureCallback lookupFailureCallback) {
    if (!mightCloseStream(basicBlock, handle, cpg)) {
        return false;
    }

    Instruction ins = handle.getInstruction();

    if ((ins instanceof INVOKEVIRTUAL) || (ins instanceof INVOKEINTERFACE)) {
        // Does this instruction close the stream?
        InvokeInstruction inv = (InvokeInstruction) ins;

        if (!frame.isValid() || !getInstanceValue(frame, inv, cpg).isInstance()) {
            return false;
        }

        // It's a close if the invoked class is any subtype of the stream
        // base class.
        // (Basically, we may not see the exact original stream class,
        // even though it's the same instance.)
        try {
            String classClosed = inv.getClassName(cpg);

            if (relatedType(classClosed)) {
                return true;
            }
            if ("java.io.ObjectOutput".equals(classClosed)) {
                return relatedType("java.io.ObjectOutputStream");
            } else if ("java.io.ObjectInput".equals(classClosed)) {
                return relatedType("java.io.ObjectInputStream");
            }
            return false;
        } catch (ClassNotFoundException e) {
            lookupFailureCallback.reportMissingClass(e);
            return false;
        }
    }

    return false;
}
 
Example 8
/**
 * @param classContext
 * @param nextHandle
 * @param next
 */
private boolean isNullTestedClose(ClassContext classContext, ALOAD load, InstructionHandle nextHandle, Instruction next) {
    if (!(next instanceof IFNULL)) {
        return false;
    }

    IFNULL ifNull = (IFNULL) next;
    InstructionHandle nextNextHandle = nextHandle.getNext(); // aload
    if (nextNextHandle == null) {
        return false;
    }
    Instruction nextInstruction = nextNextHandle.getInstruction();

    if (!(nextInstruction instanceof ALOAD)) {
        return false;
    }
    ALOAD nextLoad = (ALOAD) nextInstruction;
    if (load.getIndex() != nextLoad.getIndex()) {
        return false;
    }
    InstructionHandle nextNextNextHandle = nextNextHandle.getNext(); // invoke
    if (nextNextNextHandle == null) {
        return false;
    }
    Instruction nextNextNextInstruction = nextNextNextHandle.getInstruction();
    if (!(nextNextNextInstruction instanceof INVOKEVIRTUAL)) {
        return false;
    }
    INVOKEVIRTUAL invokeVirtual = (INVOKEVIRTUAL) nextNextNextInstruction;
    String methodName = invokeVirtual.getMethodName(classContext.getConstantPoolGen());
    String methodSig = invokeVirtual.getSignature(classContext.getConstantPoolGen());
    if (!"close".equals(methodName) || !"()V".equals(methodSig)) {
        return false;
    }
    InstructionHandle nextNextNextNextHandle = nextNextNextHandle.getNext(); // after
    return ifNull.getTarget() == nextNextNextNextHandle;
}
 
Example 9
@Override
public void visitINVOKEVIRTUAL(INVOKEVIRTUAL obj) {
    if (returnsString(obj)) {
        handleInstanceMethod(obj);
    } else {
        super.visitINVOKEVIRTUAL(obj);
    }
}
 
Example 10
private boolean isStringAppend(Instruction ins, ConstantPoolGen cpg) {
    if (ins instanceof INVOKEVIRTUAL) {
        INVOKEVIRTUAL invoke = (INVOKEVIRTUAL) ins;

        if ("append".equals(invoke.getMethodName(cpg)) && invoke.getClassName(cpg).startsWith("java.lang.StringB")) {
            String sig = invoke.getSignature(cpg);
            char firstChar = sig.charAt(1);
            return firstChar == '[' || firstChar == 'L';
        }
    }

    return false;
}
 
Example 11
public void visitInvokeOnException(Instruction obj) {
    if (!REDUNDANT_LOAD_ELIMINATION || !getFrame().hasAvailableLoads()) {
        return;
    }
    if (obj instanceof INVOKEDYNAMIC) {
        killLoadsOfObjectsPassed((INVOKEDYNAMIC) obj);
        return;
    }
    InvokeInstruction inv = (InvokeInstruction) obj;
    if ((inv instanceof INVOKEINTERFACE || inv instanceof INVOKEVIRTUAL)
            && inv.getMethodName(cpg).toLowerCase().indexOf("lock") >= 0) {
        // Don't know what this method invocation is doing.
        // Kill all loads.
        getFrame().killAllLoads();
        return;
    }
    if (inv instanceof INVOKEVIRTUAL && "cast".equals(inv.getMethodName(cpg)) && "java.lang.Class".equals(inv.getClassName(cpg))) {
        // No-op
        return;
    }
    if (inv instanceof INVOKESTATIC) {
        String methodName = inv.getName(cpg);
        if (("forName".equals(methodName) && "java.lang.Class".equals(inv.getClassName(cpg)) || "class$".equals(methodName))
                && "(Ljava/lang/String;)Ljava/lang/Class;".equals(inv.getSignature(cpg))
                || (Hierarchy.isInnerClassAccess((INVOKESTATIC) inv, cpg) && loadedFieldSet.getField(handle) != null)) {
            return;
        }
    }

    killLoadsOfObjectsPassed(inv);
    if (inv instanceof INVOKESTATIC) {
        getFrame().killAllLoadsOf(null);
    }
}
 
Example 12
public InstructionList createPrintln(final ConstantPoolGen cp, final Instruction instruction) {
    final InstructionList il = new InstructionList();

    final int out = cp.addFieldref("java.lang.System", "out", "Ljava/io/PrintStream;");
    final int println = cp.addMethodref("java.io.PrintStream", "println", "(Ljava/lang/String;)V");
    il.append(new GETSTATIC(out));
    il.append(instruction);
    il.append(new INVOKEVIRTUAL(println));

    return il;
}
 
Example 13
@Override
public void visitINVOKEVIRTUAL(INVOKEVIRTUAL obj) {
    visitInvoke(obj);
}
 
Example 14
private void analyzeMethod(Method m, ClassContext classContext) throws CFGBuilderException, DataflowAnalysisException {

        HashMap<Location, String> sslConnMap = new HashMap<Location, String>();
        HashSet<String> sslCertVerSet = new HashSet<String>();
        Location locationWeakness = null;
        String hostName = null;

        ConstantPoolGen cpg = classContext.getConstantPoolGen();
        CFG cfg = classContext.getCFG(m);

        for (Iterator<Location> i = cfg.locationIterator(); i.hasNext(); ) {
            Location location = i.next();

            Instruction inst = location.getHandle().getInstruction();

            if (inst instanceof INVOKEVIRTUAL) {
                INVOKEVIRTUAL invoke = (INVOKEVIRTUAL) inst;
                if (INSECURE_APIS.contains(invoke.getClassName(cpg)) &&
                        "setHostName".equals(invoke.getMethodName(cpg))) {
                    hostName = ByteCode.getConstantLDC(location.getHandle().getPrev(), cpg, String.class);
                }
                if (INSECURE_APIS.contains(invoke.getClassName(cpg)) &&
                        "setSSLOnConnect".equals(invoke.getMethodName(cpg))) {
                    Integer sslOn = ByteCode.getConstantInt(location.getHandle().getPrev());
                    if (sslOn != null && sslOn == 1) {
                        sslConnMap.put(location, invoke.getClassName(cpg)+hostName);
                    }
                }
                if (INSECURE_APIS.contains(invoke.getClassName(cpg)) &&
                        "setSSLCheckServerIdentity".equals(invoke.getMethodName(cpg))) {
                    Integer checkOn = ByteCode.getConstantInt(location.getHandle().getPrev());
                    if (checkOn != null && checkOn == 1) {
                        sslCertVerSet.add(invoke.getClassName(cpg)+hostName);
                    }
                }
            }
        }

        //Both conditions - setSSLOnConnect and setSSLCheckServerIdentity
        //haven't been found in the same instance (verifing instance by class name + host name)
        sslConnMap.values().removeAll(sslCertVerSet);

        if (!sslConnMap.isEmpty()) {
            for (Location key : sslConnMap.keySet()) {
                JavaClass clz = classContext.getJavaClass();
                bugReporter.reportBug(new BugInstance(this, INSECURE_SMTP_SSL, Priorities.HIGH_PRIORITY)
                        .addClass(clz)
                        .addMethod(clz, m)
                        .addSourceLine(classContext, m, key));
            }
        }
    }
 
Example 15
Source Project: spotbugs   Source File: Stream.java    License: GNU Lesser General Public License v2.1 4 votes vote down vote up
public static boolean mightCloseStream(BasicBlock basicBlock, InstructionHandle handle, ConstantPoolGen cpg) {

        Instruction ins = handle.getInstruction();

        if ((ins instanceof INVOKEVIRTUAL) || (ins instanceof INVOKEINTERFACE)) {
            // Does this instruction close the stream?
            InvokeInstruction inv = (InvokeInstruction) ins;

            // It's a close if the invoked class is any subtype of the stream
            // base class.
            // (Basically, we may not see the exact original stream class,
            // even though it's the same instance.)

            return "close".equals(inv.getName(cpg)) && "()V".equals(inv.getSignature(cpg));

        }

        return false;
    }
 
Example 16
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException {

        MethodGen methodGen = classContext.getMethodGen(method);
        if (methodGen == null) {
            return;
        }
        ConstantPoolGen cpg = methodGen.getConstantPool();
        CFG cfg = classContext.getCFG(method);
        ValueNumberDataflow vnaDataflow = classContext.getValueNumberDataflow(method);
        LockDataflow dataflow = classContext.getLockDataflow(method);

        for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
            Location location = i.next();

            InstructionHandle handle = location.getHandle();

            Instruction ins = handle.getInstruction();
            if (!(ins instanceof INVOKEVIRTUAL)) {
                continue;
            }
            INVOKEVIRTUAL inv = (INVOKEVIRTUAL) ins;

            String methodName = inv.getName(cpg);
            String methodSig = inv.getSignature(cpg);

            if (Hierarchy.isMonitorWait(methodName, methodSig) || Hierarchy.isMonitorNotify(methodName, methodSig)) {
                int numConsumed = inv.consumeStack(cpg);
                if (numConsumed == Const.UNPREDICTABLE) {
                    throw new DataflowAnalysisException("Unpredictable stack consumption", methodGen, handle);
                }

                ValueNumberFrame frame = vnaDataflow.getFactAtLocation(location);
                if (!frame.isValid()) {
                    // Probably dead code
                    continue;
                }
                if (frame.getStackDepth() - numConsumed < 0) {
                    throw new DataflowAnalysisException("Stack underflow", methodGen, handle);
                }
                ValueNumber ref = frame.getValue(frame.getNumSlots() - numConsumed);
                LockSet lockSet = dataflow.getFactAtLocation(location);
                int lockCount = lockSet.getLockCount(ref.getNumber());

                if (lockCount == 0) {
                    Collection<ValueNumber> lockedValueNumbers = lockSet.getLockedValueNumbers(frame);
                    boolean foundMatch = false;
                    for (ValueNumber v : lockedValueNumbers) {
                        if (frame.veryFuzzyMatch(ref, v)) {
                            foundMatch = true;
                            break;
                        }
                    }

                    if (!foundMatch) {

                        String type = "wait".equals(methodName) ? "MWN_MISMATCHED_WAIT" : "MWN_MISMATCHED_NOTIFY";
                        String sourceFile = classContext.getJavaClass().getSourceFileName();
                        // Report as medium priority only if the method is
                        // public.
                        // Non-public methods may be properly locked in a
                        // calling context.
                        int priority = method.isPublic() ? NORMAL_PRIORITY : LOW_PRIORITY;

                        bugAccumulator.accumulateBug(
                                new BugInstance(this, type, priority).addClassAndMethod(methodGen, sourceFile),
                                SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen, sourceFile, handle));
                    }
                }
            }
        }
        bugAccumulator.reportAccumulatedBugs();
    }
 
Example 17
@Override
public void visitINVOKEVIRTUAL(INVOKEVIRTUAL inv) {
    handleInvoke(inv);
}
 
Example 18
@Override
public void visitINVOKEVIRTUAL(INVOKEVIRTUAL obj) {
    handleInvoke(obj);
}
 
Example 19
/** @see org.apache.bcel.generic.Visitor */
public void visitINVOKEVIRTUAL(INVOKEVIRTUAL aINVOKEVIRTUAL)
{
    addInvokeReference(
        new InvokeReference(aINVOKEVIRTUAL, mCurrentPoolGen));
}
 
Example 20
/** @see org.apache.bcel.generic.Visitor */
public void visitINVOKEVIRTUAL(INVOKEVIRTUAL aINVOKEVIRTUAL)
{
    addInvokeReference(
        new InvokeReference(aINVOKEVIRTUAL, mCurrentPoolGen));
}
 
Example 21
Source Project: commons-bcel   Source File: helloify.java    License: Apache License 2.0 4 votes vote down vote up
/**
 * Patch a method.
 */
private static Method helloifyMethod(Method m) {
    final Code code = m.getCode();
    final int flags = m.getAccessFlags();
    final String name = m.getName();

    // Sanity check
    if (m.isNative() || m.isAbstract() || (code == null)) {
        return m;
    }

    // Create instruction list to be inserted at method start.
    final String mesg = "Hello from " + Utility.methodSignatureToString(m.getSignature(),
            name,
            Utility.accessToString(flags));
    final InstructionList patch = new InstructionList();
    patch.append(new GETSTATIC(out));
    patch.append(new PUSH(cp, mesg));
    patch.append(new INVOKEVIRTUAL(println));

    final MethodGen mg = new MethodGen(m, class_name, cp);
    final InstructionList il = mg.getInstructionList();
    final InstructionHandle[] ihs = il.getInstructionHandles();

    if (name.equals("<init>")) { // First let the super or other constructor be called
        for (int j = 1; j < ihs.length; j++) {
            if (ihs[j].getInstruction() instanceof INVOKESPECIAL) {
                il.append(ihs[j], patch); // Should check: method name == "<init>"
                break;
            }
        }
    } else {
        il.insert(ihs[0], patch);
    }

    // Stack size must be at least 2, since the println method takes 2 argument.
    if (code.getMaxStack() < 2) {
        mg.setMaxStack(2);
    }

    m = mg.getMethod();

    il.dispose(); // Reuse instruction handles

    return m;
}
 
Example 22
Source Project: commons-bcel   Source File: ProxyCreator.java    License: Apache License 2.0 4 votes vote down vote up
/**
 * Create JavaClass object for a simple proxy for an java.awt.event.ActionListener
 * that just prints the passed arguments, load and use it via the class loader
 * mechanism.
 */
public static void main(final String[] argv) throws Exception {
    final ClassLoader loader = ProxyCreator.class.getClassLoader();

    // instanceof won't work here ...
    // TODO this is broken; cannot ever be true now that ClassLoader has been dropped
    if (loader.getClass().toString().equals("class org.apache.bcel.util.ClassLoader")) {
        // Real class name will be set by the class loader
        final ClassGen cg = new ClassGen("foo", "java.lang.Object", "", Constants.ACC_PUBLIC,
                new String[]{"java.awt.event.ActionListener"});

        // That's important, otherwise newInstance() won't work
        cg.addEmptyConstructor(Constants.ACC_PUBLIC);

        final InstructionList il = new InstructionList();
        final ConstantPoolGen cp = cg.getConstantPool();
        final InstructionFactory factory = new InstructionFactory(cg);

        final int out = cp.addFieldref("java.lang.System", "out",
                "Ljava/io/PrintStream;");
        final int println = cp.addMethodref("java.io.PrintStream", "println",
                "(Ljava/lang/Object;)V");
        final MethodGen mg = new MethodGen(Constants.ACC_PUBLIC, Type.VOID,
                new Type[]{
                        new ObjectType("java.awt.event.ActionEvent")
                }, null, "actionPerformed", "foo", il, cp);

        // System.out.println("actionPerformed:" + event);
        il.append(new GETSTATIC(out));
        il.append(factory.createNew("java.lang.StringBuffer"));
        il.append(InstructionConstants.DUP);
        il.append(new PUSH(cp, "actionPerformed:"));
        il.append(factory.createInvoke("java.lang.StringBuffer", "<init>", Type.VOID,
                new Type[]{Type.STRING}, Constants.INVOKESPECIAL));

        il.append(new ALOAD(1));
        il.append(factory.createAppend(Type.OBJECT));
        il.append(new INVOKEVIRTUAL(println));
        il.append(InstructionConstants.RETURN);

        mg.stripAttributes(true);
        mg.setMaxStack();
        mg.setMaxLocals();
        cg.addMethod(mg.getMethod());

        final byte[] bytes = cg.getJavaClass().getBytes();

        System.out.println("Uncompressed class: " + bytes.length);

        final String s = Utility.encode(bytes, true);
        System.out.println("Encoded class: " + s.length());

        System.out.print("Creating proxy ... ");
        final ActionListener a = (ActionListener) createProxy("foo.bar.", s);
        System.out.println("Done. Now calling actionPerformed()");

        a.actionPerformed(new ActionEvent(a, ActionEvent.ACTION_PERFORMED, "hello"));
    } else {
        System.err.println("Call me with java org.apache.bcel.util.JavaWrapper ProxyCreator");
    }
}