private static <T> void appendGetDelayedCellSetterSwitch( DelayedCellSetterFactory<T, ?>[] delayedCellSetters, String classType, MethodVisitor mv, int switchStart, int switchEnd) { mv.visitVarInsn(ILOAD, 1); Label defaultLabel = new Label(); Label[] labels = newLabels(switchEnd - switchStart); mv.visitTableSwitchInsn(switchStart, switchEnd - 1, defaultLabel, labels); for (int i = switchStart; i < switchEnd; i++) { mv.visitLabel(labels[i - switchStart]); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); if (delayedCellSetters != null) { mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, classType, "delayedCellSetter" + i, "L" + DELAYED_CELL_SETTER_TYPE + ";"); } else { mv.visitInsn(ACONST_NULL); } mv.visitInsn(ARETURN); } mv.visitLabel(defaultLabel); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); }
protected void injectGetByIndex( ClassWriter classWriter, String targetClassName, List<Field> fields) { MethodVisitor methodVisitor = classWriter.visitMethod( ACC_PUBLIC, "get", "(Ljava/lang/Object;I)Ljava/lang/Object;", null, new String[] {getInternalName(ILLEGAL_ACCESS_EXCEPTION.getCanonicalName())}); Boxer boxer = new Boxer(methodVisitor); methodVisitor.visitCode(); methodVisitor.visitVarInsn(ILOAD, 2); int maxStack = 6; Label[] labels = new Label[fields.size()]; Label errorLabel = new Label(); for (int i = 0; i < fields.size(); i++) { labels[i] = new Label(); } methodVisitor.visitTableSwitchInsn(0, labels.length - 1, errorLabel, labels); if (!fields.isEmpty()) { maxStack--; for (int i = 0; i < fields.size(); i++) { Field field = fields.get(i); Class<?> type = field.getType(); String fieldDescriptor = Type.getDescriptor(type); methodVisitor.visitLabel(labels[i]); if (i == 0) methodVisitor.visitFrame(F_APPEND, 1, new Object[] {targetClassName}, 0, null); else methodVisitor.visitFrame(F_SAME, 0, null, 0, null); if (isPublic(field)) { methodVisitor.visitVarInsn(ALOAD, 1); methodVisitor.visitTypeInsn(CHECKCAST, targetClassName); methodVisitor.visitFieldInsn(GETFIELD, targetClassName, field.getName(), fieldDescriptor); boxer.box(Type.getType(type)); } else { injectReflectiveGetter(methodVisitor); } methodVisitor.visitInsn(ARETURN); } methodVisitor.visitLabel(errorLabel); methodVisitor.visitFrame(F_SAME, 0, null, 0, null); } injectException(methodVisitor, IllegalAccessException.class); methodVisitor.visitMaxs(maxStack, 3); methodVisitor.visitEnd(); }
private static <T> void appendCellValue( CellSetter<T>[] setters, boolean ignoreException, ClassWriter cw, String classType) { MethodVisitor mv; mv = cw.visitMethod(ACC_PUBLIC, "cellValue", "([CIII)V", null, null); mv.visitCode(); if (setters.length != 0) { if (ignoreException) { callCellValue(mv, classType); } else { Label l0 = new Label(); Label l1 = new Label(); Label l2 = new Label(); mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Exception"); mv.visitLabel(l0); callCellValue(mv, classType); mv.visitLabel(l1); Label l3 = new Label(); mv.visitJumpInsn(GOTO, l3); mv.visitLabel(l2); mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/Exception"}); mv.visitVarInsn(ASTORE, 5); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ILOAD, 4); mv.visitVarInsn(ALOAD, 5); mv.visitMethodInsn( INVOKEVIRTUAL, classType, "fieldError", "(ILjava/lang/Exception;)V", false); mv.visitLabel(l3); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); } } mv.visitInsn(RETURN); mv.visitMaxs(5, 6); mv.visitEnd(); }
private static void insertGetString( ClassWriter cw, String classNameInternal, ArrayList<Field> fields) { int maxStack = 6; MethodVisitor mv = cw.visitMethod( ACC_PUBLIC, "getString", "(Ljava/lang/Object;I)Ljava/lang/String;", 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 (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)) { Field field = fields.get(i); mv.visitLabel(labels[i]); mv.visitFrame(F_SAME, 0, null, 0, null); if (!Modifier.isStatic(field.getModifiers())) { mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, classNameInternal); } mv.visitFieldInsn( Modifier.isStatic(field.getModifiers()) ? GETSTATIC : GETFIELD, classNameInternal, field.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(); }
protected void injectGetIndex(ClassWriter classWriter) { MethodVisitor mv = classWriter.visitMethod(ACC_PRIVATE, "getIndex", "(Ljava/lang/String;)I", null, null); mv.visitCode(); mv.visitInsn(ICONST_0); mv.visitVarInsn(ISTORE, 2); Label forLoopLabel = new Label(); mv.visitLabel(forLoopLabel); mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] {Opcodes.INTEGER}, 0, null); mv.visitVarInsn(ILOAD, 2); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, getAccessorNameInternal(this.getTarget(), this.getAccessorType()), "fieldTable", "[Ljava/lang/reflect/Field;"); mv.visitInsn(ARRAYLENGTH); Label forLoopIncrementLabel = new Label(); mv.visitJumpInsn(IF_ICMPGE, forLoopIncrementLabel); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, getAccessorNameInternal(this.getTarget(), this.getAccessorType()), "fieldTable", "[Ljava/lang/reflect/Field;"); mv.visitVarInsn(ILOAD, 2); mv.visitInsn(AALOAD); mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/reflect/Field", "getName", "()Ljava/lang/String;", false); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false); Label equalsLabel = new Label(); mv.visitJumpInsn(IFEQ, equalsLabel); mv.visitVarInsn(ILOAD, 2); mv.visitInsn(IRETURN); mv.visitLabel(equalsLabel); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitIincInsn(2, 1); mv.visitJumpInsn(GOTO, forLoopLabel); mv.visitLabel(forLoopIncrementLabel); mv.visitFrame(Opcodes.F_CHOP, 1, null, 0, null); mv.visitInsn(ICONST_M1); mv.visitInsn(IRETURN); mv.visitMaxs(2, 3); mv.visitEnd(); }
public void visitFrame(int i, int i1, Object[] objects, int i2, Object[] objects1) { System.out.println( "visitFrame(" + i + ", " + i1 + ", " + objects + ", " + i2 + ", " + objects1 + ")"); methodVisitor.visitFrame(i, i1, objects, i2, objects1); }
@Override public void nodeDispatch(String suffix, int divide, int start, int end) { MethodVisitor mv; mv = cw.visitMethod(ACC_PRIVATE, name() + suffix, signature(), null, null); mv.visitCode(); Label startLabel = new Label(); mv.visitLabel(startLabel); final int powerOfTwo = Integer.numberOfTrailingZeros(divide); int sStart = start >> powerOfTwo; int sEnd = end >> powerOfTwo; int left = end - (sEnd << powerOfTwo); if (left > 0) { sEnd++; } Label[] labels = newLabels(sEnd - sStart); Label defaultLabel = new Label(); mv.visitVarInsn(ILOAD, argIndex()); int sub = leafStart(); if (sub != 0) { AsmUtils.addIndex(mv, sub); mv.visitInsn(ISUB); } AsmUtils.addIndex(mv, powerOfTwo); mv.visitInsn(ISHR); mv.visitVarInsn(ISTORE, maxArgIndex() + 1); mv.visitVarInsn(ILOAD, maxArgIndex() + 1); mv.visitTableSwitchInsn(sStart, sEnd - 1, defaultLabel, labels); for (int i = sStart; i < sEnd; i++) { int estart = i << powerOfTwo; int eend = Math.min(end, (i + 1) << powerOfTwo); mv.visitLabel(labels[i - sStart]); if (i == start) { mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] {Opcodes.INTEGER}, 0, null); } else { mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); } loadArguments(mv); mv.visitMethodInsn( INVOKESPECIAL, classType, name() + (divide / maxMethodSize) + "n" + estart + "t" + eend, signature(), false); if (isVoid()) { if (i < (sEnd - 1)) { mv.visitJumpInsn(GOTO, defaultLabel); } } else { mv.visitInsn(ARETURN); } } mv.visitLabel(defaultLabel); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); if (isVoid()) { mv.visitInsn(RETURN); } else { mv.visitInsn(ACONST_NULL); mv.visitInsn(ARETURN); } Label endLabel = new Label(); mv.visitLabel(endLabel); appendDebugInfo(mv, startLabel, endLabel); mv.visitMaxs(6, 5); mv.visitEnd(); }
public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { visitor.visitFrame(type, nLocal, local, nStack, stack); }
@Override public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { super.visitFrame(type, nLocal, local, nStack, stack); }
private static void insertGetPrimitive( ClassWriter cw, String classNameInternal, ArrayList<Field> fields, Type primitiveType) { 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); if (!Modifier.isStatic(field.getModifiers())) { mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, classNameInternal); } mv.visitFieldInsn( Modifier.isStatic(field.getModifiers()) ? GETSTATIC : 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(); }
private static void insertGetObject( ClassWriter cw, String classNameInternal, ArrayList<Field> fields) { int maxStack = 6; MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "get", "(Ljava/lang/Object;I)Ljava/lang/Object;", null, null); 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); mv.visitLabel(labels[i]); mv.visitFrame(F_SAME, 0, null, 0, null); if (!Modifier.isStatic(field.getModifiers())) { mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, classNameInternal); } mv.visitFieldInsn( Modifier.isStatic(field.getModifiers()) ? GETSTATIC : 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; } mv.visitInsn(ARETURN); } mv.visitLabel(defaultLabel); mv.visitFrame(F_SAME, 0, null, 0, null); } insertThrowExceptionForFieldNotFound(mv); mv.visitMaxs(maxStack, 3); mv.visitEnd(); }
private static void insertSetObject( ClassWriter cw, String classNameInternal, ArrayList<Field> fields) { int maxStack = 6; MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "set", "(Ljava/lang/Object;ILjava/lang/Object;)V", null, null); 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); if (!Modifier.isStatic(field.getModifiers())) { 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; } mv.visitFieldInsn( Modifier.isStatic(field.getModifiers()) ? PUTSTATIC : 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(); }
protected void injectConstructor(ClassWriter classWriter) { String resultName = getAccessorNameInternal(this.getTarget(), this.getAccessorType()); MethodVisitor methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); methodVisitor.visitCode(); methodVisitor.visitVarInsn(ALOAD, 0); methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); ; methodVisitor.visitTypeInsn(NEW, "java/util/ArrayList"); methodVisitor.visitInsn(DUP); methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/util/ArrayList", "<init>", "()V", false); methodVisitor.visitVarInsn(ASTORE, 1); methodVisitor.visitVarInsn(ALOAD, 0); methodVisitor.visitMethodInsn( INVOKEVIRTUAL, resultName, "getTargetClass", "()Ljava/lang/Class;", false); methodVisitor.visitVarInsn(ASTORE, 2); Label whileLoop = new Label(); // enter the "while (currentClass != Object.class)" loop methodVisitor.visitLabel(whileLoop); methodVisitor.visitFrame( Opcodes.F_FULL, 3, new Object[] {resultName, "java/util/List", "java/lang/Class"}, 0, new Object[] {}); methodVisitor.visitVarInsn(ALOAD, 2); methodVisitor.visitLdcInsn(Type.getType("Ljava/lang/Object;")); Label classNotObjectComparer = new Label(); // compares the current class to Object.class aka currentClass != Object.class methodVisitor.visitJumpInsn(IF_ACMPEQ, classNotObjectComparer); methodVisitor.visitVarInsn(ALOAD, 2); methodVisitor.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getDeclaredFields", "()[Ljava/lang/reflect/Field;", false); methodVisitor.visitVarInsn(ASTORE, 3); methodVisitor.visitVarInsn(ALOAD, 3); methodVisitor.visitInsn(ARRAYLENGTH); methodVisitor.visitVarInsn(ISTORE, 4); methodVisitor.visitInsn(ICONST_0); methodVisitor.visitVarInsn(ISTORE, 5); Label cachingForLoop = new Label(); // this loop handles the storing of the fields (to the list) methodVisitor.visitLabel(cachingForLoop); methodVisitor.visitFrame( Opcodes.F_APPEND, 3, new Object[] {"[Ljava/lang/reflect/Field;", Opcodes.INTEGER, Opcodes.INTEGER}, 0, null); methodVisitor.visitVarInsn(ILOAD, 5); methodVisitor.visitVarInsn(ILOAD, 4); Label cachingForLoopIncrementLabel = new Label(); // handles the looping of the fields methodVisitor.visitJumpInsn(IF_ICMPGE, cachingForLoopIncrementLabel); methodVisitor.visitVarInsn(ALOAD, 3); methodVisitor.visitVarInsn(ILOAD, 5); methodVisitor.visitInsn(AALOAD); methodVisitor.visitVarInsn(ASTORE, 6); methodVisitor.visitVarInsn(ALOAD, 1); methodVisitor.visitVarInsn(ALOAD, 6); methodVisitor.visitMethodInsn( INVOKEINTERFACE, "java/util/List", "add", "(Ljava/lang/Object;)Z", true); methodVisitor.visitInsn(POP); methodVisitor.visitIincInsn(5, 1); methodVisitor.visitJumpInsn(GOTO, cachingForLoop); methodVisitor.visitLabel(cachingForLoopIncrementLabel); methodVisitor.visitFrame(Opcodes.F_CHOP, 3, null, 0, null); methodVisitor.visitVarInsn(ALOAD, 2); methodVisitor.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getSuperclass", "()Ljava/lang/Class;", false); methodVisitor.visitVarInsn(ASTORE, 2); methodVisitor.visitJumpInsn(GOTO, whileLoop); methodVisitor.visitLabel(classNotObjectComparer); methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null); methodVisitor.visitVarInsn(ALOAD, 0); methodVisitor.visitVarInsn(ALOAD, 1); methodVisitor.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "size", "()I", true); methodVisitor.visitTypeInsn(ANEWARRAY, "java/lang/reflect/Field"); methodVisitor.visitFieldInsn(PUTFIELD, resultName, "fieldTable", "[Ljava/lang/reflect/Field;"); methodVisitor.visitInsn(ICONST_0); methodVisitor.visitVarInsn(ISTORE, 3); Label storingForLoop = new Label(); // this for loop goes about storing the fields in the array defined in the // class methodVisitor.visitLabel(storingForLoop); methodVisitor.visitFrame(Opcodes.F_APPEND, 1, new Object[] {Opcodes.INTEGER}, 0, null); methodVisitor.visitVarInsn(ILOAD, 3); methodVisitor.visitVarInsn(ALOAD, 0); methodVisitor.visitFieldInsn(GETFIELD, resultName, "fieldTable", "[Ljava/lang/reflect/Field;"); methodVisitor.visitInsn(ARRAYLENGTH); Label storage = new Label(); // gets the field at position x and stores it in the cache (fieldTable) methodVisitor.visitJumpInsn(IF_ICMPGE, storage); methodVisitor.visitVarInsn(ALOAD, 0); methodVisitor.visitFieldInsn(GETFIELD, resultName, "fieldTable", "[Ljava/lang/reflect/Field;"); methodVisitor.visitVarInsn(ILOAD, 3); methodVisitor.visitVarInsn(ALOAD, 1); methodVisitor.visitVarInsn(ILOAD, 3); methodVisitor.visitMethodInsn( INVOKEINTERFACE, "java/util/List", "get", "(I)Ljava/lang/Object;", true); methodVisitor.visitTypeInsn(CHECKCAST, "java/lang/reflect/Field"); methodVisitor.visitInsn(AASTORE); methodVisitor.visitIincInsn(3, 1); methodVisitor.visitJumpInsn(GOTO, storingForLoop); methodVisitor.visitLabel(storage); methodVisitor.visitFrame(Opcodes.F_CHOP, 1, null, 0, null); methodVisitor.visitInsn(RETURN); methodVisitor.visitMaxs(4, 7); methodVisitor.visitEnd(); }
@Override public void visitFrame( final int type, final int nLocal, final Object[] local, final int nStack, final Object[] stack) { if (insnCount == lastFrame) { throw new IllegalStateException("At most one frame can be visited at a given code location."); } lastFrame = insnCount; int mLocal; int mStack; switch (type) { case Opcodes.F_NEW: case Opcodes.F_FULL: mLocal = Integer.MAX_VALUE; mStack = Integer.MAX_VALUE; break; case Opcodes.F_SAME: mLocal = 0; mStack = 0; break; case Opcodes.F_SAME1: mLocal = 0; mStack = 1; break; case Opcodes.F_APPEND: case Opcodes.F_CHOP: mLocal = 3; mStack = 0; break; default: throw new IllegalArgumentException("Invalid frame type " + type); } if (nLocal > mLocal) { throw new IllegalArgumentException("Invalid nLocal=" + nLocal + " for frame type " + type); } if (nStack > mStack) { throw new IllegalArgumentException("Invalid nStack=" + nStack + " for frame type " + type); } if (type != Opcodes.F_CHOP) { if (nLocal > 0 && (local == null || local.length < nLocal)) { throw new IllegalArgumentException("Array local[] is shorter than nLocal"); } for (int i = 0; i < nLocal; ++i) { checkFrameValue(local[i]); } } if (nStack > 0 && (stack == null || stack.length < nStack)) { throw new IllegalArgumentException("Array stack[] is shorter than nStack"); } for (int i = 0; i < nStack; ++i) { checkFrameValue(stack[i]); } if (type == Opcodes.F_NEW) { ++expandedFrames; } else { ++compressedFrames; } if (expandedFrames > 0 && compressedFrames > 0) { throw new RuntimeException("Expanded and compressed frames must not be mixed."); } super.visitFrame(type, nLocal, local, nStack, stack); }