Example usage for org.objectweb.asm MethodVisitor visitFrame

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

Introduction

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

Prototype

public void visitFrame(final int type, final int numLocal, final Object[] local, final int numStack,
        final Object[] stack) 

Source Link

Document

Visits the current state of the local variables and operand stack elements.

Usage

From source file:jtaint.ServletAdapter.java

License:Apache License

private void buildGetPathTranslatedWrapper(MethodVisitor mv) {
    mv.visitCode();/*from   w ww  . j  a  va  2s .c o m*/

    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKESPECIAL, className, ByteCodeUtil.internalName("getPathTranslated"),
            "()Ljava/lang/String;");
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, className, ByteCodeUtil.internalName("isHttpServletRequest"), "Z");
    Label l0 = new Label();
    mv.visitJumpInsn(IFEQ, l0);

    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKESTATIC, "jtaint/HttpUtil", "getPathTranslated",
            "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;");

    mv.visitLabel(l0);
    if (version == V1_6)
        mv.visitFrame(F_SAME1, 0, null, 1, new Object[] { "java/lang/String" });
    mv.visitInsn(ARETURN);
    mv.visitMaxs(2, 1);
    mv.visitEnd();
}

From source file:jtaint.ServletAdapter.java

License:Apache License

private void buildHtmlValidatorWrapper(MethodVisitor mv, String name, String desc) {
    mv.visitCode();//from   www . j a va  2 s.co m

    Type[] t = Type.getArgumentTypes(desc);
    Type r = Type.getReturnType(desc);

    mv.visitVarInsn(ALOAD, 0);
    int l = 1;

    for (int i = 0; i < t.length; l += t[i].getSize(), i++)
        mv.visitVarInsn(t[i].getOpcode(ILOAD), l);
    mv.visitMethodInsn(INVOKESPECIAL, className, ByteCodeUtil.internalName(name), desc);

    Label l0 = new Label();
    mv.visitInsn(DUP);
    mv.visitJumpInsn(IFNULL, l0);

    mv.visitInsn(DUP);
    mv.visitMethodInsn(INVOKEVIRTUAL, r.getInternalName(), ByteCodeUtil.internalName("getHtmlValidator"),
            "()Ljtaint/HtmlValidator;");
    mv.visitJumpInsn(IFNONNULL, l0);

    /* Okay, we have a valid print object and null html validator, time 
     * to initialize...
     */

    mv.visitInsn(DUP);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKESTATIC, "jtaint/HttpUtil", "getHtmlValidator",
            "(Ljava/lang/Object;)Ljtaint/HtmlValidator;");
    mv.visitMethodInsn(INVOKEVIRTUAL, r.getInternalName(), ByteCodeUtil.internalName("setHtmlValidator"),
            "(Ljtaint/HtmlValidator;)V");

    mv.visitLabel(l0);
    if (version == V1_6)
        mv.visitFrame(F_SAME1, 0, null, 1, new Object[] { r.getInternalName() });
    mv.visitInsn(ARETURN);

    mv.visitMaxs(Math.max(l, 3), l);
    mv.visitEnd();
}

From source file:jtaint.SqlAdapter.java

License:Apache License

private void addSqlValidator() {
    MethodVisitor mv = cv.visitMethod(ACC_PUBLIC
            //[ifJava4]
            + ACC_SYNCHRONIZED//from w  w w . j a  va2 s  .co m
    //[fiJava4] 
            , ByteCodeUtil.internalName("sqlValidator"), "()Ljtaint/SqlValidator;", null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, className, ByteCodeUtil.internalName("validator"), "Ljtaint/SqlValidator;");
    mv.visitInsn(DUP);

    Label l0 = new Label();
    mv.visitJumpInsn(IFNULL, l0);
    mv.visitInsn(ARETURN);

    mv.visitLabel(l0);
    if (version == V1_6)
        mv.visitFrame(F_SAME1, 0, null, 1, new Object[] { "jtaint/SqlValidator" });

    mv.visitInsn(POP);

    /* XXX This is an industrial-sized barrel of fun. We have to avoid
     * infinite recursion here when initializing the validator field --
     * i.e. when sqlValidator is called for the first time. In this case,
     * what can happen is:
     * connection.sqlValidator -> jtaint.SqlUtil.getSqlValidator
     * -> Connection.getDatabaseMetadata 
     * -> Connection.sqlValidator ->
     * -> jtaint.SqlUtil.getSqlValidator
     * -> Connection.getDatabaseMetadata
     * ... (repeat last three steps forever), where -> denotes a method call
     * So if we ever find that we already own the lock that we are about
     * to acquire, then we return an EmptySqlValidator to break
     * the recursion(Note that once the recursion unwinds, the validator
     * field will be correctly set, so we will begin returning the correct
     * sql validator. This corner case applies only during initialization).
     */

    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, className, ByteCodeUtil.internalName("lockObj"), "Ljava/lang/Object;");
    mv.visitInsn(DUP);
    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Thread", "holdsLock", "(Ljava/lang/Object;)Z");
    Label l1 = new Label();
    mv.visitJumpInsn(IFEQ, l1);

    /* Break the recursion */
    mv.visitFieldInsn(GETSTATIC, "jtaint/EmptySqlValidator", "INSTANCE", "Ljtaint/EmptySqlValidator;");
    mv.visitInsn(ARETURN);

    /* No recursion -- acquire the lock and initialize our field */
    mv.visitLabel(l1);
    if (version == V1_6)
        mv.visitFrame(F_SAME1, 0, null, 1, new Object[] { "java/lang/Object" });
    mv.visitInsn(DUP);
    mv.visitInsn(MONITORENTER);

    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, className, ByteCodeUtil.internalName("validator"), "Ljtaint/SqlValidator;");
    mv.visitInsn(DUP);
    Label l2 = new Label();
    mv.visitJumpInsn(IFNULL, l2);
    mv.visitInsn(SWAP);
    mv.visitInsn(MONITOREXIT);
    mv.visitInsn(ARETURN);

    mv.visitLabel(l2);
    if (version == V1_6)
        mv.visitFrame(F_FULL, 1, new Object[] { className }, 2,
                new Object[] { "java/lang/Object", "jtaint/SqlValidator" });
    mv.visitInsn(POP);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitInsn(DUP);
    mv.visitMethodInsn(INVOKESTATIC, "jtaint/SqlUtil", "getSqlValidator",
            "(Ljava/lang/Object;)Ljtaint/SqlValidator;");
    mv.visitInsn(DUP_X1);
    mv.visitFieldInsn(PUTFIELD, className, ByteCodeUtil.internalName("validator"), "Ljtaint/SqlValidator;");
    mv.visitInsn(SWAP);
    mv.visitInsn(MONITOREXIT);
    mv.visitInsn(ARETURN);

    mv.visitMaxs(4, 1);
    mv.visitEnd();
}

From source file:jtaint.StringAdapter.java

License:Apache License

/** Create new method that compares its argument to the package-private
 * constant Character.ERROR. This must be exported for jtaint helper
 * methods. Equivalent to the following Java code:
 *
 * public static boolean isError(int c) {
 *     return c == Character.ERROR;/*w  w  w. j  a  va2s . c om*/
 * }
 */
private void addIsErrorMethod(ClassVisitor cv) {
    boolean isError = false;
    MethodVisitor mv = cv.visitMethod(ACC_PUBLIC + ACC_STATIC, ByteCodeUtil.internalName("isError"), "(I)Z",
            null, null);
    mv.visitCode();
    mv.visitVarInsn(ILOAD, 0);

    /* Test to see if java/lang/Character uses ERROR or CHAR_ERROR 
     * If ERROR cannot be found, an getDeclaredFields throws an exception
     */
    try {
        Character.class.getDeclaredField("ERROR");
        isError = true;
    } catch (Throwable th) {
        /* ignore */ }

    if (isError)
        mv.visitFieldInsn(GETSTATIC, "java/lang/Character", "ERROR", "I");
    else
        mv.visitFieldInsn(GETSTATIC, "java/lang/Character", "CHAR_ERROR", "C");

    Label l = new Label();
    mv.visitJumpInsn(IF_ICMPEQ, l);
    mv.visitInsn(ICONST_0);
    mv.visitInsn(IRETURN);

    mv.visitLabel(l);
    if (version == V1_6)
        mv.visitFrame(F_SAME, 0, null, 0, null);

    mv.visitInsn(ICONST_1);
    mv.visitInsn(IRETURN);
    mv.visitMaxs(2, 1);
    mv.visitEnd();
}

From source file:jtaint.StringAdapter.java

License:Apache License

/** Create a new method that returns a Taint object representing the taint
 * for this String. Equivalent to the following Java code:
 * /*www  .j  a v a 2 s .  c  o  m*/
 * public Taint taint() {
 *     if (!tainted) {
 *         return null;
 *     } else {
 *         return jtaint.StringUtil.stringToTaint(value, count);
 *     }
 * }
 */

private void addTaintMethod(ClassVisitor cv) {
    MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, ByteCodeUtil.internalName("taint"), "()Ljtaint/Taint;", null,
            null);
    mv.visitCode();

    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, className, ByteCodeUtil.internalName("tainted"), "Z");

    Label l = new Label();
    mv.visitJumpInsn(IFNE, l);
    mv.visitInsn(ACONST_NULL);
    mv.visitInsn(ARETURN);

    mv.visitLabel(l);
    if (version == V1_6)
        mv.visitFrame(F_SAME, 0, null, 0, null);

    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, className, "value", "[C");
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, className, "count", "I");
    mv.visitMethodInsn(INVOKESTATIC, "jtaint/StringUtil", "stringToTaint", "([CI)Ljtaint/Taint;");
    mv.visitInsn(ARETURN);
    mv.visitMaxs(4, 1);
    mv.visitEnd();
}

From source file:jtaint.StringAdapter.java

License:Apache License

/** Add a new constructor to a create a (partially or fully) tainted 
 * String. Equivalent to the following Java code:
 *
 * public String(String original, Taint t) {
 *     super();/*from w w  w .j av  a  2s.co  m*/
 *     this.count = original.count;
 *
 *     if (!t.isTainted()) {
 *         this.offset = original.offset;
 *         this.value = original.value;
 *         this.tainted = original.tainted;
 *         return
 *     }
 *
 *     this.offset = 0;
 *     this.value = jtaint.StringUtil.taintToString(original, t)
 *     if (this.value.length == this.count)
 *         this.tainted = false;
 *     else
 *         this.tainted = true;
 *     return;
 * The final check (if value.length == count) is true only when an error
 * occurs during the execution of taintToString
 */

private void addConstructor(ClassVisitor cv) {
    MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "<init>", "(Ljava/lang/String;Ljtaint/Taint;)V", null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");

    copyField(mv, "count", "I");

    Label l0 = new Label();
    mv.visitVarInsn(ALOAD, 2);
    mv.visitMethodInsn(INVOKEVIRTUAL, "jtaint/Taint", "isTainted", "()Z");
    mv.visitJumpInsn(IFNE, l0);

    /* Taint object is actually untainted, copy all fields and return */
    copyField(mv, "offset", "I");
    copyField(mv, "value", "[C");
    copyField(mv, ByteCodeUtil.internalName("tainted"), "Z");
    mv.visitInsn(RETURN);

    mv.visitLabel(l0);
    if (version == V1_6)
        mv.visitFrame(F_SAME, 0, null, 0, null);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitInsn(ICONST_0);
    mv.visitFieldInsn(PUTFIELD, className, "offset", "I");

    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ALOAD, 1);
    mv.visitVarInsn(ALOAD, 2);
    mv.visitMethodInsn(INVOKESTATIC, "jtaint/StringUtil", "taintToString",
            "(Ljava/lang/String;Ljtaint/Taint;)[C");
    mv.visitInsn(DUP_X1);
    mv.visitFieldInsn(PUTFIELD, className, "value", "[C");
    mv.visitInsn(ARRAYLENGTH);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, className, "count", "I");

    Label l1 = new Label();
    mv.visitJumpInsn(IF_ICMPEQ, l1);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitInsn(ICONST_1);
    mv.visitFieldInsn(PUTFIELD, className, ByteCodeUtil.internalName("tainted"), "Z");
    mv.visitInsn(RETURN);

    mv.visitLabel(l1);
    if (version == V1_6)
        mv.visitFrame(F_SAME, 0, null, 0, null);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitInsn(ICONST_0);
    mv.visitFieldInsn(PUTFIELD, className, ByteCodeUtil.internalName("tainted"), "Z");

    mv.visitInsn(RETURN);

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

From source file:jtaint.XssAdapter.java

License:Apache License

private void buildWriteIntWrapper(final MethodVisitor mv, final String methodName, final String desc) {
    new XssLockBuilder(mv, version, className, methodName, desc) {
        public void onUnlocked() {
            mv.visitVarInsn(ALOAD, 0);/*from  ww w  .jav  a2s . c om*/
            mv.visitMethodInsn(INVOKEVIRTUAL, className, ByteCodeUtil.internalName("getHtmlValidator"),
                    "()Ljtaint/HtmlValidator;");

            if ("javax/servlet/ServletOutputStream".equals(className)) {
                mv.visitVarInsn(ILOAD, 1);
                mv.visitInsn(I2B);
                mv.visitMethodInsn(INVOKEVIRTUAL, "jtaint/HtmlValidator", "write", "(B)V");
            } else if ("java/io/PrintWriter".equals(className)) {
                mv.visitVarInsn(ILOAD, 1);
                mv.visitInsn(I2C);
                mv.visitMethodInsn(INVOKEVIRTUAL, "jtaint/HtmlValidator", "print", "(C)V");
            } else {
                /* Runtime check required */
                Label l0 = new Label();
                Label l1 = new Label();

                mv.visitVarInsn(ALOAD, 0);
                mv.visitTypeInsn(INSTANCEOF, "java/io/PrintWriter");
                mv.visitJumpInsn(IFNE, l1);

                /* If-branch, we're a ServletOutputStream.  */
                mv.visitVarInsn(ILOAD, 1);
                mv.visitInsn(I2B);
                mv.visitMethodInsn(INVOKEVIRTUAL, "jtaint/HtmlValidator", "write", "(B)V");
                mv.visitJumpInsn(GOTO, l0);

                /* Else-branch, we're a PrintWriter  */
                mv.visitLabel(l1);
                if (version == V1_6)
                    mv.visitFrame(F_SAME1, 0, null, 1, new Object[] { "jtaint/HtmlValidator" });

                mv.visitVarInsn(ILOAD, 1);
                mv.visitInsn(I2C);
                mv.visitMethodInsn(INVOKEVIRTUAL, "jtaint/HtmlValidator", "print", "(C)V");
                mv.visitLabel(l0);
                if (version == V1_6) {
                    mv.visitFrame(F_SAME, 0, null, 0, null);
                    /* We can't end on a visitFrame because 
                     * InstrumentationLockAdapter performs a visitFrame 
                     * after this method completes. Two consecutive 
                     * visitFrames cause the Java 6 type checker to barf, 
                     * so just pad with a single NOP.
                     */
                    mv.visitInsn(NOP);
                }
            }
        }
    }.build();
}

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 www  . 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 .  ja v  a2 s .  c  o 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   ww  w  .ja v  a2 s .  c o  m
    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();
}