Example usage for org.objectweb.asm MethodVisitor visitTableSwitchInsn

List of usage examples for org.objectweb.asm MethodVisitor visitTableSwitchInsn

Introduction

In this page you can find the example usage for org.objectweb.asm MethodVisitor visitTableSwitchInsn.

Prototype

public void visitTableSwitchInsn(final int min, final int max, final Label dflt, final Label... labels) 

Source Link

Document

Visits a TABLESWITCH instruction.

Usage

From source file:javaone2015.con7442.indyprotector.BootstrapMethodGenerator.java

License:Apache License

/**
 * Generate bootstrap method/*from   www.ja  v  a 2s  . com*/
 */
public void insertMethod(ClassVisitor target) {
    MethodVisitor mv = target.visitMethod(ACC_PRIVATE + ACC_STATIC, BSM_NAME, BSM_SIG, null, null);
    mv.visitCode();
    Label l0 = new Label();
    Label l1 = new Label();
    Label l2 = new Label();
    mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Exception");
    mv.visitInsn(ACONST_NULL);
    mv.visitVarInsn(ASTORE, 7);
    mv.visitLabel(l0);
    mv.visitVarInsn(ALOAD, 4);
    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;",
            false);
    mv.visitVarInsn(ASTORE, 8);
    mv.visitLdcInsn(Type.getType(targetClassName));
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getClassLoader", "()Ljava/lang/ClassLoader;", false);
    mv.visitVarInsn(ASTORE, 9);
    mv.visitVarInsn(ALOAD, 6);
    mv.visitVarInsn(ALOAD, 9);
    mv.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodType", "fromMethodDescriptorString",
            "(Ljava/lang/String;Ljava/lang/ClassLoader;)Ljava/lang/invoke/MethodType;", false);
    mv.visitVarInsn(ASTORE, 10);
    mv.visitVarInsn(ILOAD, 3);
    Label l3 = new Label();
    Label l4 = new Label();
    Label l5 = new Label();
    mv.visitTableSwitchInsn(182, 185, l4, new Label[] { l3, l4, l5, l3 });
    mv.visitLabel(l5);
    mv.visitFrame(Opcodes.F_FULL, 11,
            new Object[] { "java/lang/invoke/MethodHandles$Lookup", "java/lang/String",
                    "java/lang/invoke/MethodType", Opcodes.INTEGER, "java/lang/String", "java/lang/String",
                    "java/lang/String", "java/lang/invoke/MethodHandle", "java/lang/Class",
                    "java/lang/ClassLoader", "java/lang/invoke/MethodType" },
            0, new Object[] {});
    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ALOAD, 8);
    mv.visitVarInsn(ALOAD, 5);
    mv.visitVarInsn(ALOAD, 10);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandles$Lookup", "findStatic",
            "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;",
            false);
    mv.visitVarInsn(ASTORE, 7);
    Label l6 = new Label();
    mv.visitJumpInsn(GOTO, l6);
    mv.visitLabel(l3);
    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ALOAD, 8);
    mv.visitVarInsn(ALOAD, 5);
    mv.visitVarInsn(ALOAD, 10);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandles$Lookup", "findVirtual",
            "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;",
            false);
    mv.visitVarInsn(ASTORE, 7);
    mv.visitJumpInsn(GOTO, l6);
    mv.visitLabel(l4);
    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
    mv.visitTypeInsn(NEW, "java/lang/BootstrapMethodError");
    mv.visitInsn(DUP);
    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/BootstrapMethodError", "<init>", "()V", false);
    mv.visitInsn(ATHROW);
    mv.visitLabel(l6);
    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
    mv.visitVarInsn(ALOAD, 7);
    mv.visitVarInsn(ALOAD, 2);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "asType",
            "(Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;", false);
    mv.visitVarInsn(ASTORE, 7);
    mv.visitLabel(l1);
    Label l7 = new Label();
    mv.visitJumpInsn(GOTO, l7);
    mv.visitLabel(l2);
    mv.visitFrame(Opcodes.F_FULL, 8,
            new Object[] { "java/lang/invoke/MethodHandles$Lookup", "java/lang/String",
                    "java/lang/invoke/MethodType", Opcodes.INTEGER, "java/lang/String", "java/lang/String",
                    "java/lang/String", "java/lang/invoke/MethodHandle" },
            1, new Object[] { "java/lang/Exception" });
    mv.visitVarInsn(ASTORE, 8);
    mv.visitTypeInsn(NEW, "java/lang/BootstrapMethodError");
    mv.visitInsn(DUP);
    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/BootstrapMethodError", "<init>", "()V", false);
    mv.visitInsn(ATHROW);
    mv.visitLabel(l7);
    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
    mv.visitTypeInsn(NEW, "java/lang/invoke/ConstantCallSite");
    mv.visitInsn(DUP);
    mv.visitVarInsn(ALOAD, 7);
    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/invoke/ConstantCallSite", "<init>",
            "(Ljava/lang/invoke/MethodHandle;)V", false);
    mv.visitInsn(ARETURN);
    mv.visitMaxs(4, 11);
    mv.visitEnd();

}

From source file:kilim.analysis.CallWeaver.java

License:Open Source License

/**
 * After the pausable method call is over, we have four possibilities. The
 * called method yielded, or it returned normally. Orthogonally, we have
 * saved state or not. fiber.up() returns the combined status
 * /*from  ww w  .ja  v a2  s  . c  o m*/
?     * <pre>
 *                     
 * switch (fiber.up()) {
 *    default:
 *    0: goto RESUME; // Not yielding , no State --  resume normal operations
 *    1: goto RESTORE; // Not yielding, has State -- restore state before resuming
 *    2: goto SAVE; // Yielding, no state -- save state before unwinding stack
 *    3: goto UNWIND // Yielding, has state -- nothing to do but unwind.
 * }
 * SAVE:
 *     ...
 *     xRETURN
 * UNWIND:
 *     ...
 *     xRETURN
 * RESTORE:
 *     ...
 *     // fall through to RESUME
 * RESUME:
 *     ... original code
 * </pre>
 * 
 * @param mv
 * 
 */
void genPostCall(MethodVisitor mv) {
    loadVar(mv, TOBJECT, methodWeaver.getFiberVar());
    mv.visitMethodInsn(INVOKEVIRTUAL, FIBER_CLASS, "up", "()I");
    Label restoreLabel = new Label();
    Label saveLabel = new Label();
    Label unwindLabel = new Label();
    Label[] labels = new Label[] { resumeLabel, restoreLabel, saveLabel, unwindLabel };
    mv.visitTableSwitchInsn(0, 3, resumeLabel, labels);
    genSave(mv, saveLabel);
    genUnwind(mv, unwindLabel);
    genRestore(mv, restoreLabel);
    mv.visitLabel(resumeLabel);
}

From source file:kilim.analysis.MethodWeaver.java

License:Open Source License

/**
 * // ww  w .ja  v  a  2  s  .c  o m
 * Say there are two invocations to two pausable methods obj.f(int)
 * (virtual) and fs(double) (a static call) ; load fiber from last arg, and
 * save it in a fresh register ; lest it gets stomped on. This is because we
 * only patch locally, and don't change the other instructions.
 * 
 * <pre>
 *     aload lastVar
 *     dup
 *     astore fiberVar 
 *     switch (fiber.pc) { 
 *       default: 0: START 
 *       1: F_PASS_DOWN 
 *       2: FS_PASS_DOWN 
 *     }
 * </pre>
 */
private void genPrelude(MethodVisitor mv) {
    assert isPausable : "MethodWeaver.genPrelude called for nonPausable method";
    MethodFlow mf = methodFlow;
    // load fiber from last var
    int lastVar = getFiberArgVar();

    mv.visitVarInsn(ALOAD, lastVar);
    if (lastVar < fiberVar) {
        if (callWeavers.size() > 0) {
            mv.visitInsn(DUP); // for storing into fiberVar
        }
        mv.visitVarInsn(ASTORE, getFiberVar());
    }

    if (callWeavers.size() == 0) {
        // Can happen if Task.getCurrentTask() is the only pausable method
        // call. We don't need the rest of the prelude.
        return;
    }

    mv.visitFieldInsn(GETFIELD, FIBER_CLASS, "pc", D_INT);
    // The prelude doesn't need more than two words in the stack.
    // The callweaver gen* methods may need more. 
    ensureMaxStack(2);

    // switch stmt
    Label startLabel = mf.getOrCreateLabelAtPos(0);
    Label errLabel = new Label();

    Label[] labels = new Label[callWeavers.size() + 1];
    labels[0] = startLabel;
    for (int i = 0; i < callWeavers.size(); i++) {
        labels[i + 1] = new Label();
    }
    // TODO       mv.visitTableSwitchInsn(0, callWeavers.size(), startLabel, labels);
    mv.visitTableSwitchInsn(0, callWeavers.size(), errLabel, labels);

    mv.visitLabel(errLabel);
    mv.visitMethodInsn(INVOKESTATIC, FIBER_CLASS, "wrongPC", "()V");
    // Generate pass through down code, one for each pausable method
    // invocation
    int last = callWeavers.size() - 1;
    for (int i = 0; i <= last; i++) {
        CallWeaver cw = callWeavers.get(i);
        mv.visitLabel(labels[i + 1]);
        cw.genRewind(mv);
    }
    mv.visitLabel(startLabel);
}

From source file:kr.debop4j.core.reflect.FieldAccess.java

License:Apache License

static private void insertSetObject(ClassWriter cw, String classNameInternal, List<Field> fields) {
    int maxStack = 6;
    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "set", "(Ljava/lang/Object;ILjava/lang/Object;)V", null,
            null);//from w  w w . j a  v a2s .c  o m
    mv.visitCode();
    mv.visitVarInsn(ILOAD, 2);

    if (!fields.isEmpty()) {
        maxStack--;
        Label[] labels = new Label[fields.size()];
        for (int i = 0, n = labels.length; i < n; i++)
            labels[i] = new Label();
        Label defaultLabel = new Label();
        mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);

        for (int i = 0, n = labels.length; i < n; i++) {
            Field field = fields.get(i);
            Type fieldType = Type.getType(field.getType());

            mv.visitLabel(labels[i]);
            mv.visitFrame(F_SAME, 0, null, 0, null);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitTypeInsn(CHECKCAST, classNameInternal);
            mv.visitVarInsn(ALOAD, 3);

            switch (fieldType.getSort()) {
            case Type.BOOLEAN:
                mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean");
                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");
                break;
            case Type.BYTE:
                mv.visitTypeInsn(CHECKCAST, "java/lang/Byte");
                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B");
                break;
            case Type.CHAR:
                mv.visitTypeInsn(CHECKCAST, "java/lang/Character");
                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C");
                break;
            case Type.SHORT:
                mv.visitTypeInsn(CHECKCAST, "java/lang/Short");
                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");
                break;
            case Type.INT:
                mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");
                break;
            case Type.FLOAT:
                mv.visitTypeInsn(CHECKCAST, "java/lang/Float");
                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");
                break;
            case Type.LONG:
                mv.visitTypeInsn(CHECKCAST, "java/lang/Long");
                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");
                break;
            case Type.DOUBLE:
                mv.visitTypeInsn(CHECKCAST, "java/lang/Double");
                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");
                break;
            case Type.ARRAY:
                mv.visitTypeInsn(CHECKCAST, fieldType.getDescriptor());
                break;
            case Type.OBJECT:
                mv.visitTypeInsn(CHECKCAST, fieldType.getInternalName());
                break;
            default:
            }

            mv.visitFieldInsn(PUTFIELD, classNameInternal, field.getName(), fieldType.getDescriptor());
            mv.visitInsn(RETURN);
        }

        mv.visitLabel(defaultLabel);
        mv.visitFrame(F_SAME, 0, null, 0, null);
    }
    mv = insertThrowExceptionForFieldNotFound(mv);
    mv.visitMaxs(maxStack, 4);
    mv.visitEnd();
}

From source file:kr.debop4j.core.reflect.FieldAccess.java

License:Apache License

static private void insertGetObject(ClassWriter cw, String classNameInternal, List<Field> fields) {
    int maxStack = 6;
    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "get", "(Ljava/lang/Object;I)Ljava/lang/Object;", null, null);
    mv.visitCode();/*from w w w . jav a2  s  .co m*/
    mv.visitVarInsn(ILOAD, 2);

    if (!fields.isEmpty()) {
        maxStack--;
        Label[] labels = new Label[fields.size()];
        for (int i = 0, n = labels.length; i < n; i++)
            labels[i] = new Label();
        Label defaultLabel = new Label();
        mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);

        for (int i = 0, n = labels.length; i < n; i++) {
            Field field = fields.get(i);

            mv.visitLabel(labels[i]);
            mv.visitFrame(F_SAME, 0, null, 0, null);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitTypeInsn(CHECKCAST, classNameInternal);
            mv.visitFieldInsn(GETFIELD, classNameInternal, field.getName(),
                    Type.getDescriptor(field.getType()));

            Type fieldType = Type.getType(field.getType());

            switch (fieldType.getSort()) {
            case Type.BOOLEAN:
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
                break;
            case Type.BYTE:
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
                break;
            case Type.CHAR:
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
                break;
            case Type.SHORT:
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
                break;
            case Type.INT:
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
                break;
            case Type.FLOAT:
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
                break;
            case Type.LONG:
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
                break;
            case Type.DOUBLE:
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
                break;
            default:
            }

            mv.visitInsn(ARETURN);
        }

        mv.visitLabel(defaultLabel);
        mv.visitFrame(F_SAME, 0, null, 0, null);
    }
    insertThrowExceptionForFieldNotFound(mv);
    mv.visitMaxs(maxStack, 3);
    mv.visitEnd();
}

From source file:kr.debop4j.core.reflect.FieldAccess.java

License:Apache License

static private void insertGetString(ClassWriter cw, String classNameInternal, List<Field> fields) {
    int maxStack = 6;
    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "getString", "(Ljava/lang/Object;I)Ljava/lang/String;", null,
            null);//from   w ww . j a va2 s  .  com
    mv.visitCode();
    mv.visitVarInsn(ILOAD, 2);

    if (!fields.isEmpty()) {
        maxStack--;
        Label[] labels = new Label[fields.size()];
        Label labelForInvalidTypes = new Label();
        boolean hasAnyBadTypeLabel = false;
        for (int i = 0, n = labels.length; i < n; i++) {
            if (fields.get(i).getType().equals(String.class))
                labels[i] = new Label();
            else {
                labels[i] = labelForInvalidTypes;
                hasAnyBadTypeLabel = true;
            }
        }
        Label defaultLabel = new Label();
        mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);

        for (int i = 0, n = labels.length; i < n; i++) {
            if (!labels[i].equals(labelForInvalidTypes)) {
                mv.visitLabel(labels[i]);
                mv.visitFrame(F_SAME, 0, null, 0, null);
                mv.visitVarInsn(ALOAD, 1);
                mv.visitTypeInsn(CHECKCAST, classNameInternal);
                mv.visitFieldInsn(GETFIELD, classNameInternal, fields.get(i).getName(), "Ljava/lang/String;");
                mv.visitInsn(ARETURN);
            }
        }
        // Rest of fields: different type
        if (hasAnyBadTypeLabel) {
            mv.visitLabel(labelForInvalidTypes);
            mv.visitFrame(F_SAME, 0, null, 0, null);
            insertThrowExceptionForFieldType(mv, "String");
        }
        // Default: field not found
        mv.visitLabel(defaultLabel);
        mv.visitFrame(F_SAME, 0, null, 0, null);
    }
    insertThrowExceptionForFieldNotFound(mv);
    mv.visitMaxs(maxStack, 3);
    mv.visitEnd();
}

From source file:kr.debop4j.core.reflect.FieldAccess.java

License:Apache License

static private void insertSetPrimitive(ClassWriter cw, String classNameInternal, List<Field> fields,
        Type primitiveType) {// w w w .  jav  a 2 s.c om
    int maxStack = 6;
    int maxLocals = 4; // See correction below for LLOAD and DLOAD
    final String setterMethodName;
    final String typeNameInternal = primitiveType.getDescriptor();
    final int loadValueInstruction;
    switch (primitiveType.getSort()) {
    case Type.BOOLEAN:
        setterMethodName = "setBoolean";
        loadValueInstruction = ILOAD;
        break;
    case Type.BYTE:
        setterMethodName = "setByte";
        loadValueInstruction = ILOAD;
        break;
    case Type.CHAR:
        setterMethodName = "setChar";
        loadValueInstruction = ILOAD;
        break;
    case Type.SHORT:
        setterMethodName = "setShort";
        loadValueInstruction = ILOAD;
        break;
    case Type.INT:
        setterMethodName = "setInt";
        loadValueInstruction = ILOAD;
        break;
    case Type.FLOAT:
        setterMethodName = "setFloat";
        loadValueInstruction = FLOAD;
        break;
    case Type.LONG:
        setterMethodName = "setLong";
        loadValueInstruction = LLOAD;
        maxLocals++; // (LLOAD and DLOAD actually load two slots)
        break;
    case Type.DOUBLE:
        setterMethodName = "setDouble";
        loadValueInstruction = DLOAD; // (LLOAD and DLOAD actually load two slots)
        maxLocals++;
        break;
    default:
        setterMethodName = "set";
        loadValueInstruction = ALOAD;
        break;
    }
    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, setterMethodName,
            "(Ljava/lang/Object;I" + typeNameInternal + ")V", null, null);
    mv.visitCode();
    mv.visitVarInsn(ILOAD, 2);

    if (!fields.isEmpty()) {
        maxStack--;
        Label[] labels = new Label[fields.size()];
        Label labelForInvalidTypes = new Label();
        boolean hasAnyBadTypeLabel = false;
        for (int i = 0, n = labels.length; i < n; i++) {
            if (Type.getType(fields.get(i).getType()).equals(primitiveType))
                labels[i] = new Label();
            else {
                labels[i] = labelForInvalidTypes;
                hasAnyBadTypeLabel = true;
            }
        }
        Label defaultLabel = new Label();
        mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);

        for (int i = 0, n = labels.length; i < n; i++) {
            if (!labels[i].equals(labelForInvalidTypes)) {
                mv.visitLabel(labels[i]);
                mv.visitFrame(F_SAME, 0, null, 0, null);
                mv.visitVarInsn(ALOAD, 1);
                mv.visitTypeInsn(CHECKCAST, classNameInternal);
                mv.visitVarInsn(loadValueInstruction, 3);
                mv.visitFieldInsn(PUTFIELD, classNameInternal, fields.get(i).getName(), typeNameInternal);
                mv.visitInsn(RETURN);
            }
        }
        // Rest of fields: different type
        if (hasAnyBadTypeLabel) {
            mv.visitLabel(labelForInvalidTypes);
            mv.visitFrame(F_SAME, 0, null, 0, null);
            insertThrowExceptionForFieldType(mv, primitiveType.getClassName());
        }
        // Default: field not found
        mv.visitLabel(defaultLabel);
        mv.visitFrame(F_SAME, 0, null, 0, null);
    }
    mv = insertThrowExceptionForFieldNotFound(mv);
    mv.visitMaxs(maxStack, maxLocals);
    mv.visitEnd();
}

From source file:kr.debop4j.core.reflect.FieldAccess.java

License:Apache License

static private void insertGetPrimitive(ClassWriter cw, String classNameInternal, List<Field> fields,
        Type primitiveType) {//from   w  ww .j av a  2  s. c  o m
    int maxStack = 6;
    final String getterMethodName;
    final String typeNameInternal = primitiveType.getDescriptor();
    final int returnValueInstruction;
    switch (primitiveType.getSort()) {
    case Type.BOOLEAN:
        getterMethodName = "getBoolean";
        returnValueInstruction = IRETURN;
        break;
    case Type.BYTE:
        getterMethodName = "getByte";
        returnValueInstruction = IRETURN;
        break;
    case Type.CHAR:
        getterMethodName = "getChar";
        returnValueInstruction = IRETURN;
        break;
    case Type.SHORT:
        getterMethodName = "getShort";
        returnValueInstruction = IRETURN;
        break;
    case Type.INT:
        getterMethodName = "getInt";
        returnValueInstruction = IRETURN;
        break;
    case Type.FLOAT:
        getterMethodName = "getFloat";
        returnValueInstruction = FRETURN;
        break;
    case Type.LONG:
        getterMethodName = "getLong";
        returnValueInstruction = LRETURN;
        break;
    case Type.DOUBLE:
        getterMethodName = "getDouble";
        returnValueInstruction = DRETURN;
        break;
    default:
        getterMethodName = "get";
        returnValueInstruction = ARETURN;
        break;
    }
    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, getterMethodName, "(Ljava/lang/Object;I)" + typeNameInternal,
            null, null);
    mv.visitCode();
    mv.visitVarInsn(ILOAD, 2);

    if (!fields.isEmpty()) {
        maxStack--;
        Label[] labels = new Label[fields.size()];
        Label labelForInvalidTypes = new Label();
        boolean hasAnyBadTypeLabel = false;
        for (int i = 0, n = labels.length; i < n; i++) {
            if (Type.getType(fields.get(i).getType()).equals(primitiveType))
                labels[i] = new Label();
            else {
                labels[i] = labelForInvalidTypes;
                hasAnyBadTypeLabel = true;
            }
        }
        Label defaultLabel = new Label();
        mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);

        for (int i = 0, n = labels.length; i < n; i++) {
            Field field = fields.get(i);
            if (!labels[i].equals(labelForInvalidTypes)) {
                mv.visitLabel(labels[i]);
                mv.visitFrame(F_SAME, 0, null, 0, null);
                mv.visitVarInsn(ALOAD, 1);
                mv.visitTypeInsn(CHECKCAST, classNameInternal);
                mv.visitFieldInsn(GETFIELD, classNameInternal, field.getName(), typeNameInternal);
                mv.visitInsn(returnValueInstruction);
            }
        }
        // Rest of fields: different type
        if (hasAnyBadTypeLabel) {
            mv.visitLabel(labelForInvalidTypes);
            mv.visitFrame(F_SAME, 0, null, 0, null);
            insertThrowExceptionForFieldType(mv, primitiveType.getClassName());
        }
        // Default: field not found
        mv.visitLabel(defaultLabel);
        mv.visitFrame(F_SAME, 0, null, 0, null);
    }
    mv = insertThrowExceptionForFieldNotFound(mv);
    mv.visitMaxs(maxStack, 3);
    mv.visitEnd();
}

From source file:kr.debop4j.core.reflect.MethodAccess.java

License:Apache License

/**
 *  ? ? ??   MethodAccess .//from www . jav a2s .c  o m
 *
 * @param type 
 * @return the method access
 */
public static MethodAccess get(final Class type) {
    Guard.shouldNotBeNull(type, "type");

    List<Method> methods = Lists.newArrayList();
    Class nextClass = type;
    while (nextClass != Object.class) {
        Method[] declaredMethods = nextClass.getDeclaredMethods();
        for (Method method : declaredMethods) {
            int modifiers = method.getModifiers();
            if (Modifier.isStatic(modifiers))
                continue;
            if (Modifier.isPrivate(modifiers))
                continue;
            methods.add(method);
        }
        nextClass = nextClass.getSuperclass();
    }

    Class[][] parameterTypes = new Class[methods.size()][];
    String[] methodNames = new String[methods.size()];
    for (int i = 0, size = methodNames.length; i < size; i++) {
        Method method = methods.get(i);
        methodNames[i] = method.getName();
        parameterTypes[i] = method.getParameterTypes();
    }

    String className = type.getName();
    String accessClassName = className + "MethodAccess";
    if (accessClassName.startsWith("java."))
        accessClassName = ReflectConsts.BASE_PACKAGE + "." + accessClassName;

    Class accessClass;
    AccessClassLoader loader = AccessClassLoader.get(type);

    synchronized (loader) {
        try {
            accessClass = loader.loadClass(accessClassName);
        } catch (ClassNotFoundException ignored) {
            String accessClassNameInternal = accessClassName.replace('.', '/');
            String classNameInternal = className.replace('.', '/');

            ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
            MethodVisitor mv;
            cw.visit(V1_1, ACC_PUBLIC + ACC_SUPER, accessClassNameInternal, null,
                    ReflectConsts.METHOD_ACCESS_PATH, null);
            {
                mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
                mv.visitCode();
                mv.visitVarInsn(ALOAD, 0);
                mv.visitMethodInsn(INVOKESPECIAL, ReflectConsts.METHOD_ACCESS_PATH, "<init>", "()V");
                mv.visitInsn(RETURN);
                mv.visitMaxs(0, 0);
                mv.visitEnd();
            }
            {
                mv = cw.visitMethod(ACC_PUBLIC + ACC_VARARGS, "invoke",
                        "(Ljava/lang/Object;I[Ljava/lang/Object;)Ljava/lang/Object;", null, null);
                mv.visitCode();

                if (!methods.isEmpty()) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitTypeInsn(CHECKCAST, classNameInternal);
                    mv.visitVarInsn(ASTORE, 4);

                    mv.visitVarInsn(ILOAD, 2);
                    Label[] labels = new Label[methods.size()];
                    for (int i = 0, n = labels.length; i < n; i++)
                        labels[i] = new Label();
                    Label defaultLabel = new Label();
                    mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);

                    StringBuilder buffer = new StringBuilder(128);
                    for (int i = 0, n = labels.length; i < n; i++) {
                        mv.visitLabel(labels[i]);
                        if (i == 0)
                            mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] { classNameInternal }, 0, null);
                        else
                            mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                        mv.visitVarInsn(ALOAD, 4);

                        buffer.setLength(0);
                        buffer.append('(');

                        Method method = methods.get(i);
                        Class[] paramTypes = method.getParameterTypes();
                        for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
                            mv.visitVarInsn(ALOAD, 3);
                            mv.visitIntInsn(BIPUSH, paramIndex);
                            mv.visitInsn(AALOAD);
                            Type paramType = Type.getType(paramTypes[paramIndex]);
                            switch (paramType.getSort()) {
                            case Type.BOOLEAN:
                                mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean");
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");
                                break;
                            case Type.BYTE:
                                mv.visitTypeInsn(CHECKCAST, "java/lang/Byte");
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B");
                                break;
                            case Type.CHAR:
                                mv.visitTypeInsn(CHECKCAST, "java/lang/Character");
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C");
                                break;
                            case Type.SHORT:
                                mv.visitTypeInsn(CHECKCAST, "java/lang/Short");
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");
                                break;
                            case Type.INT:
                                mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");
                                break;
                            case Type.FLOAT:
                                mv.visitTypeInsn(CHECKCAST, "java/lang/Float");
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");
                                break;
                            case Type.LONG:
                                mv.visitTypeInsn(CHECKCAST, "java/lang/Long");
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");
                                break;
                            case Type.DOUBLE:
                                mv.visitTypeInsn(CHECKCAST, "java/lang/Double");
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");
                                break;
                            case Type.ARRAY:
                                mv.visitTypeInsn(CHECKCAST, paramType.getDescriptor());
                                break;
                            case Type.OBJECT:
                                mv.visitTypeInsn(CHECKCAST, paramType.getInternalName());
                                break;
                            }
                            buffer.append(paramType.getDescriptor());
                        }

                        buffer.append(')');
                        buffer.append(Type.getDescriptor(method.getReturnType()));
                        mv.visitMethodInsn(INVOKEVIRTUAL, classNameInternal, method.getName(),
                                buffer.toString());

                        switch (Type.getType(method.getReturnType()).getSort()) {
                        case Type.VOID:
                            mv.visitInsn(ACONST_NULL);
                            break;
                        case Type.BOOLEAN:
                            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf",
                                    "(Z)Ljava/lang/Boolean;");
                            break;
                        case Type.BYTE:
                            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf",
                                    "(B)Ljava/lang/Byte;");
                            break;
                        case Type.CHAR:
                            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf",
                                    "(C)Ljava/lang/Character;");
                            break;
                        case Type.SHORT:
                            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf",
                                    "(S)Ljava/lang/Short;");
                            break;
                        case Type.INT:
                            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf",
                                    "(I)Ljava/lang/Integer;");
                            break;
                        case Type.FLOAT:
                            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf",
                                    "(F)Ljava/lang/Float;");
                            break;
                        case Type.LONG:
                            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf",
                                    "(J)Ljava/lang/Long;");
                            break;
                        case Type.DOUBLE:
                            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf",
                                    "(D)Ljava/lang/Double;");
                            break;
                        }

                        mv.visitInsn(ARETURN);
                    }

                    mv.visitLabel(defaultLabel);
                    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                }
                mv.visitTypeInsn(NEW, "java/lang/IllegalArgumentException");
                mv.visitInsn(DUP);
                mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
                mv.visitInsn(DUP);
                mv.visitLdcInsn("Method not found: ");
                mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V");
                mv.visitVarInsn(ILOAD, 2);
                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                        "(I)Ljava/lang/StringBuilder;");
                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString",
                        "()Ljava/lang/String;");
                mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalArgumentException", "<init>",
                        "(Ljava/lang/String;)V");
                mv.visitInsn(ATHROW);
                mv.visitMaxs(0, 0);
                mv.visitEnd();
            }
            cw.visitEnd();
            byte[] data = cw.toByteArray();
            accessClass = loader.defineClass(accessClassName, data);
        }
    }

    try {
        MethodAccess access = (MethodAccess) accessClass.newInstance();
        access.methodNames = methodNames;
        access.parameterTypes = parameterTypes;

        return access;
    } catch (Exception ex) {
        throw new RuntimeException("Error constructing method access class=[" + accessClassName + "]", ex);
    }
}

From source file:net.wpm.reflectasm.ClassAccess.java

License:Open Source License

private static void insertNewInstance(ClassWriter cw, String classNameInternal, ClassInfo info) {
    MethodVisitor mv;
    mv = cw.visitMethod(ACC_PUBLIC + ACC_VARARGS, "newInstance", "(I[Ljava/lang/Object;)Ljava/lang/Object;",
            null, null);/*from w w w . j  a  v a  2s  .c  om*/
    mv.visitCode();

    int n = info.constructorModifiers.length;

    if (n != 0) {
        mv.visitVarInsn(ILOAD, 1);
        Label[] labels = new Label[n];
        for (int i = 0; i < n; i++)
            labels[i] = new Label();
        Label defaultLabel = new Label();
        mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);

        StringBuilder buffer = new StringBuilder(128);
        for (int i = 0; i < n; i++) {
            mv.visitLabel(labels[i]);
            if (i == 0)
                mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] { classNameInternal }, 0, null);
            else
                mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);

            mv.visitTypeInsn(NEW, classNameInternal);
            mv.visitInsn(DUP);

            buffer.setLength(0);
            buffer.append('(');

            Class<?>[] paramTypes = info.constructorParameterTypes[i];
            for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
                mv.visitVarInsn(ALOAD, 2);
                mv.visitIntInsn(BIPUSH, paramIndex);
                mv.visitInsn(AALOAD);
                Type paramType = Type.getType(paramTypes[paramIndex]);
                unbox(mv, paramType);
                buffer.append(paramType.getDescriptor());
            }
            buffer.append(")V");
            mv.visitMethodInsn(INVOKESPECIAL, classNameInternal, "<init>", buffer.toString(), false);
            mv.visitInsn(ARETURN);
        }
        mv.visitLabel(defaultLabel);
        mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
    }
    mv.visitTypeInsn(NEW, "java/lang/IllegalArgumentException");
    mv.visitInsn(DUP);
    mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
    mv.visitInsn(DUP);
    mv.visitLdcInsn("Constructor not found: ");
    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V", false);
    mv.visitVarInsn(ILOAD, 1);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(I)Ljava/lang/StringBuilder;",
            false);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false);
    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalArgumentException", "<init>", "(Ljava/lang/String;)V",
            false);
    mv.visitInsn(ATHROW);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
}