List of usage examples for org.objectweb.asm MethodVisitor visitFrame
public void visitFrame(final int type, final int numLocal, final Object[] local, final int numStack, final Object[] stack)
From source file:org.jacoco.core.internal.instr.DuplicateFrameEliminatorTest.java
License:Open Source License
private void frame(MethodVisitor mv) { mv.visitFrame(Opcodes.NEW, 1, new Object[] { Opcodes.INTEGER }, 0, new Object[0]); }
From source file:org.jacoco.core.internal.instr.InterfaceFieldProbeArrayStrategy.java
License:Open Source License
private void createInitMethod(final ClassVisitor cv, final int probeCount) { final MethodVisitor mv = cv.visitMethod(InstrSupport.INITMETHOD_ACC, InstrSupport.INITMETHOD_NAME, InstrSupport.INITMETHOD_DESC, null, null); mv.visitCode();/*from w w w. j av a 2s . c o m*/ // Load the value of the static data field: mv.visitFieldInsn(Opcodes.GETSTATIC, className, InstrSupport.DATAFIELD_NAME, InstrSupport.DATAFIELD_DESC); mv.visitInsn(Opcodes.DUP); // Stack[1]: [Z // Stack[0]: [Z // Skip initialization when we already have a data array: final Label alreadyInitialized = new Label(); mv.visitJumpInsn(Opcodes.IFNONNULL, alreadyInitialized); // Stack[0]: [Z mv.visitInsn(Opcodes.POP); final int size = accessorGenerator.generateDataAccessor(classId, className, probeCount, mv); // Stack[0]: [Z // Return the class' probe array: mv.visitFrame(Opcodes.F_NEW, 0, FRAME_LOCALS_EMPTY, 1, FRAME_STACK_ARRZ); mv.visitLabel(alreadyInitialized); mv.visitInsn(Opcodes.ARETURN); mv.visitMaxs(Math.max(size, 2), 0); // Maximum local stack size is 2 mv.visitEnd(); }
From source file:org.jadira.reflection.access.asm.AsmClassAccess.java
License:Apache License
private static void enhanceForGetValueObject(ClassVisitor cw, String accessClassNm, String clazzNm, Field[] fields) {//w w w. ja v a2 s . com MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "getValue", "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, accessClassNm, "fieldNames", "[Ljava/lang/String;"); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn(INVOKESTATIC, "java/util/Arrays", "binarySearch", "([Ljava/lang/Object;Ljava/lang/Object;)I"); mv.visitVarInsn(ISTORE, 3); mv.visitVarInsn(ILOAD, 3); final int maxStack; if (fields.length > 0) { maxStack = 5; Label[] labels = constructLabels(fields); 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[i]; mv.visitLabel(labels[i]); mv.visitFrame(F_SAME, 0, null, 0, null); mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, clazzNm); mv.visitFieldInsn(GETFIELD, clazzNm, 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); } else { maxStack = 6; } enhanceForThrowingException(mv, IllegalArgumentException.class, "Field was not found", "Ljava/lang/Object;", ALOAD, 2); mv.visitMaxs(maxStack, 4); mv.visitEnd(); }
From source file:org.jadira.reflection.access.asm.AsmClassAccess.java
License:Apache License
private static void enhanceForPutValueObject(ClassVisitor cw, String accessClassNm, String clazzNm, Field[] fields) {/* w w w . j a v a 2s . c o m*/ int maxStack = 6; MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "putValue", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, accessClassNm, "fieldNames", "[Ljava/lang/String;"); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn(INVOKESTATIC, "java/util/Arrays", "binarySearch", "([Ljava/lang/Object;Ljava/lang/Object;)I"); mv.visitVarInsn(ISTORE, 4); mv.visitVarInsn(ILOAD, 4); if (fields.length > 0) { maxStack = 5; Label[] labels = constructLabels(fields); 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[i]; mv.visitLabel(labels[i]); mv.visitFrame(F_SAME, 0, null, 0, null); mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, clazzNm); mv.visitVarInsn(ALOAD, 3); Type fieldType = Type.getType(field.getType()); 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(PUTFIELD, clazzNm, field.getName(), fieldType.getDescriptor()); mv.visitInsn(RETURN); } mv.visitLabel(defaultLabel); mv.visitFrame(F_SAME, 0, null, 0, null); } else { maxStack = 6; } enhanceForThrowingException(mv, IllegalArgumentException.class, "Field was not found", "Ljava/lang/Object;", ALOAD, 2); mv.visitMaxs(maxStack, 5); mv.visitEnd(); }
From source file:org.jadira.reflection.access.asm.AsmClassAccess.java
License:Apache License
private static void enhanceForPutValuePrimitive(ClassVisitor cw, String accessClassNm, String clazzNm, Field[] fields, Type type) { final String methodName; final String typeNm = type.getDescriptor(); final int instruction; switch (type.getSort()) { case BOOLEAN: methodName = "putBooleanValue"; instruction = ILOAD;//w ww .j a va2 s . co m break; case BYTE: methodName = "putByteValue"; instruction = ILOAD; break; case CHAR: methodName = "putCharValue"; instruction = ILOAD; break; case SHORT: methodName = "putShortValue"; instruction = ILOAD; break; case INT: methodName = "putIntValue"; instruction = ILOAD; break; case FLOAT: methodName = "putFloatValue"; instruction = FLOAD; break; case LONG: methodName = "putLongValue"; instruction = LLOAD; break; case DOUBLE: methodName = "putDoubleValue"; instruction = DLOAD; break; default: methodName = "put" + type.getInternalName().lastIndexOf('/') + "Value"; instruction = ALOAD; break; } int offset = (instruction == LLOAD || instruction == DLOAD) ? 1 : 0; int maxStack = 6; MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, methodName, "(Ljava/lang/Object;Ljava/lang/String;" + typeNm + ")V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, accessClassNm, "fieldNames", "[Ljava/lang/String;"); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn(INVOKESTATIC, "java/util/Arrays", "binarySearch", "([Ljava/lang/Object;Ljava/lang/Object;)I"); mv.visitVarInsn(ISTORE, 4 + offset); mv.visitVarInsn(ILOAD, 4 + offset); if (fields.length > 0) { maxStack = 6; Label[] labels = new Label[fields.length]; Label labelForInvalidTypes = new Label(); boolean hasAnyBadTypeLabel = false; for (int i = 0, n = labels.length; i < n; i++) { if (Type.getType(fields[i].getType()).equals(type)) 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[i]; mv.visitLabel(labels[i]); mv.visitFrame(F_SAME, 0, null, 0, null); mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, clazzNm); mv.visitVarInsn(instruction, 3); mv.visitFieldInsn(PUTFIELD, clazzNm, field.getName(), typeNm); mv.visitInsn(RETURN); } } if (hasAnyBadTypeLabel) { mv.visitLabel(labelForInvalidTypes); mv.visitFrame(F_SAME, 0, null, 0, null); enhanceForThrowingException(mv, IllegalArgumentException.class, type.getClassName(), typeNm, instruction, 3); } mv.visitLabel(defaultLabel); mv.visitFrame(F_SAME, 0, null, 0, null); } final int maxLocals = 5 + offset; enhanceForThrowingException(mv, IllegalArgumentException.class, "Field was not found", typeNm, instruction, 3); mv.visitMaxs(maxStack, maxLocals); mv.visitEnd(); }
From source file:org.jadira.reflection.access.asm.AsmClassAccess.java
License:Apache License
private static void enhanceForGetValuePrimitive(ClassVisitor cw, String accessClassNm, String clazzNm, Field[] fields, Type type) { String methodName;//w w w .j a va 2s . c om final String typeNm = type.getDescriptor(); final int instruction; switch (type.getSort()) { case Type.BOOLEAN: methodName = "getBooleanValue"; instruction = IRETURN; break; case Type.BYTE: methodName = "getByteValue"; instruction = IRETURN; break; case Type.CHAR: methodName = "getCharValue"; instruction = IRETURN; break; case Type.SHORT: methodName = "getShortValue"; instruction = IRETURN; break; case Type.INT: methodName = "getIntValue"; instruction = IRETURN; break; case Type.FLOAT: methodName = "getFloatValue"; instruction = FRETURN; break; case Type.LONG: methodName = "getLongValue"; instruction = LRETURN; break; case Type.DOUBLE: methodName = "getDoubleValue"; instruction = DRETURN; break; default: methodName = "getValue"; instruction = ARETURN; break; } MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, methodName, "(Ljava/lang/Object;Ljava/lang/String;)" + typeNm, null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, accessClassNm, "fieldNames", "[Ljava/lang/String;"); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn(INVOKESTATIC, "java/util/Arrays", "binarySearch", "([Ljava/lang/Object;Ljava/lang/Object;)I"); mv.visitVarInsn(ISTORE, 3); mv.visitVarInsn(ILOAD, 3); final int maxStack; if (fields.length > 0) { maxStack = 5; Label[] labels = constructLabels(fields); 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[i]; mv.visitLabel(labels[i]); mv.visitFrame(F_SAME, 0, null, 0, null); mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, clazzNm); mv.visitFieldInsn(GETFIELD, clazzNm, field.getName(), typeNm); mv.visitInsn(instruction); } mv.visitLabel(defaultLabel); mv.visitFrame(F_SAME, 0, null, 0, null); } else { maxStack = 6; } enhanceForThrowingException(mv, IllegalArgumentException.class, "Field was not found", "Ljava/lang/Object;", ALOAD, 2); mv.visitMaxs(maxStack, 4); mv.visitEnd(); }
From source file:org.jadira.reflection.access.asm.AsmClassAccess.java
License:Apache License
private static void enhanceForInvokeMethod(ClassVisitor cw, String accessClassNm, String clazzNm, Method[] methods) {/*from www . j a v a2 s.co m*/ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_VARARGS, "invokeMethod", "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", null, null); mv.visitCode(); if (methods.length > 0) { mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, clazzNm); mv.visitVarInsn(ASTORE, 4); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn(INVOKESPECIAL, "org/jadira/reflection/access/asm/AsmClassAccess", "getMethodIndex", "(Ljava/lang/reflect/Method;)I"); mv.visitVarInsn(ISTORE, 5); mv.visitVarInsn(ILOAD, 5); Label[] labels = constructLabels(methods); Label defaultLabel = new Label(); mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels); for (int i = 0; i < labels.length; i++) { Method method = methods[i]; Class<?>[] parameterTypes = method.getParameterTypes(); mv.visitLabel(labels[i]); if (i == 0) { mv.visitFrame(F_APPEND, 1, new Object[] { clazzNm }, 0, null); } else { mv.visitFrame(F_SAME, 0, null, 0, null); } mv.visitVarInsn(ALOAD, 4); StringBuilder methodDescriptor = new StringBuilder("("); for (int parameterIdx = 0; parameterIdx < parameterTypes.length; parameterIdx++) { Type type = Type.getType(parameterTypes[parameterIdx]); mv.visitVarInsn(ALOAD, 3); mv.visitIntInsn(BIPUSH, parameterIdx); mv.visitInsn(AALOAD); switch (type.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, type.getDescriptor()); break; case Type.OBJECT: mv.visitTypeInsn(CHECKCAST, type.getInternalName()); break; } methodDescriptor.append(type.getDescriptor()); } methodDescriptor.append(')'); methodDescriptor.append(Type.getDescriptor(method.getReturnType())); mv.visitMethodInsn(INVOKEVIRTUAL, clazzNm, method.getName(), methodDescriptor.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(F_SAME, 0, null, 0, null); } enhanceForThrowingException(mv, IllegalArgumentException.class, "Method not found", "Ljava/lang/Object;", ALOAD, 2); mv.visitMaxs(8, 6); mv.visitEnd(); }
From source file:org.javachannel.examples.brokenverifier.VerifierTest.java
License:Apache License
@Test public void generateComparator() { final String slashName = "test/Verifier"; final Object[] EMPTY_OBJECT_ARRAY = new Object[0]; ClassWriter cw = new ClassWriter(0); cw.visit(V1_7, ACC_PUBLIC | ACC_SYNTHETIC, slashName, null, "java/util/HashSet", null); Label lOtherSuper = new Label(); Label lDoSomething = new Label(); MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); mv.visitCode();/*from w w w. j a va 2s .co m*/ mv.visitFrame(F_NEW, 1, new Object[] { UNINITIALIZED_THIS }, 0, EMPTY_OBJECT_ARRAY); mv.visitJumpInsn(GOTO, lOtherSuper); mv.visitFrame(F_NEW, 1, new Object[] { UNINITIALIZED_THIS }, 0, EMPTY_OBJECT_ARRAY); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "java/util/HashSet", "<init>", "()V", false); mv.visitFrame(F_NEW, 1, new Object[] { slashName }, 0, EMPTY_OBJECT_ARRAY); mv.visitLabel(lDoSomething); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/HashSet", "size", "()I", false); mv.visitInsn(POP); mv.visitInsn(RETURN); mv.visitFrame(F_NEW, 1, new Object[] { UNINITIALIZED_THIS }, 0, EMPTY_OBJECT_ARRAY); mv.visitLabel(lOtherSuper); mv.visitVarInsn(ALOAD, 0); mv.visitIntInsn(BIPUSH, 1); mv.visitMethodInsn(INVOKESPECIAL, "java/util/HashSet", "<init>", "(I)V", false); mv.visitJumpInsn(GOTO, lDoSomething); mv.visitMaxs(3, 1); mv.visitEnd(); cw.visitEnd(); byte[] b = cw.toByteArray(); MyClassLoader cl = new MyClassLoader(); Class c = cl.defineClass(slashName.replace('/', '.'), b); Method[] m = c.getMethods(); }
From source file:org.jephyr.activeobject.instrument.ActiveObjectClassAdapter.java
License:Open Source License
private static void visitFrame(MethodVisitor mv, Type type) { switch (type.getSort()) { case Type.VOID: mv.visitFrame(F_SAME, 0, null, 0, null); break;/*from ww w .ja v a2 s .c o m*/ case Type.BOOLEAN: case Type.CHAR: case Type.BYTE: case Type.SHORT: case Type.INT: mv.visitFrame(F_SAME1, 0, null, 1, new Object[] { INTEGER }); break; case Type.FLOAT: mv.visitFrame(F_SAME1, 0, null, 1, new Object[] { FLOAT }); break; case Type.LONG: mv.visitFrame(F_SAME1, 0, null, 1, new Object[] { LONG }); break; case Type.DOUBLE: mv.visitFrame(F_SAME1, 0, null, 1, new Object[] { DOUBLE }); break; default: mv.visitFrame(F_SAME1, 0, null, 1, new Object[] { type.getInternalName() }); } }
From source file:org.jupiter.common.util.FastMethodAccessor.java
License:Apache License
private static FastMethodAccessor create(Class<?> type) { ArrayList<Method> methods = Lists.newArrayList(); boolean isInterface = type.isInterface(); if (!isInterface) { Class nextClass = type;/*w w w. j a v a 2s . c om*/ while (nextClass != Object.class) { addDeclaredMethodsToList(nextClass, methods); nextClass = nextClass.getSuperclass(); } } else { recursiveAddInterfaceMethodsToList(type, methods); } int n = methods.size(); String[] methodNames = new String[n]; Class<?>[][] parameterTypes_s = new Class[n][]; Class<?>[] returnTypes = new Class[n]; for (int i = 0; i < n; i++) { Method method = methods.get(i); methodNames[i] = method.getName(); parameterTypes_s[i] = method.getParameterTypes(); returnTypes[i] = method.getReturnType(); } String className = type.getName(); String accessorClassName = className + "_FastMethodAccessor"; String accessorClassNameInternal = accessorClassName.replace('.', '/'); String classNameInternal = className.replace('.', '/'); String superClassNameInternal = FastMethodAccessor.class.getName().replace('.', '/'); ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); MethodVisitor mv; cw.visit(V1_1, ACC_PUBLIC + ACC_SUPER, accessorClassNameInternal, null, superClassNameInternal, null); // ? { mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, superClassNameInternal, "<init>", "()V", false); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } // : public Object invoke(Object obj, int methodIndex, Object... args); { mv = cw.visitMethod(ACC_PUBLIC + ACC_VARARGS, "invoke", "(Ljava/lang/Object;I[Ljava/lang/Object;)Ljava/lang/Object;", null, null); mv.visitCode(); if (n > 0) { // ?? obj (Class<?> type) mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, classNameInternal); mv.visitVarInsn(ASTORE, 4); // ? switch ? mv.visitVarInsn(ILOAD, 2); Label[] labels = new Label[n]; for (int i = 0; i < n; i++) { labels[i] = new Label(); } Label defaultLabel = new Label(); // the default handler block mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels); StringBuilder buf = 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.visitVarInsn(ALOAD, 4); buf.setLength(0); buf.append('('); Class<?>[] parameterTypes = parameterTypes_s[i]; Class<?> returnType = returnTypes[i]; for (int p_index = 0; p_index < parameterTypes.length; p_index++) { mv.visitVarInsn(ALOAD, 3); mv.visitIntInsn(BIPUSH, p_index); mv.visitInsn(AALOAD); // ?, (?) Type p_type = Type.getType(parameterTypes[p_index]); switch (p_type.getSort()) { case Type.BOOLEAN: mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false); break; case Type.BYTE: mv.visitTypeInsn(CHECKCAST, "java/lang/Byte"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false); break; case Type.CHAR: mv.visitTypeInsn(CHECKCAST, "java/lang/Character"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false); break; case Type.SHORT: mv.visitTypeInsn(CHECKCAST, "java/lang/Short"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false); break; case Type.INT: mv.visitTypeInsn(CHECKCAST, "java/lang/Integer"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false); break; case Type.FLOAT: mv.visitTypeInsn(CHECKCAST, "java/lang/Float"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false); break; case Type.LONG: mv.visitTypeInsn(CHECKCAST, "java/lang/Long"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false); break; case Type.DOUBLE: mv.visitTypeInsn(CHECKCAST, "java/lang/Double"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false); break; case Type.ARRAY: mv.visitTypeInsn(CHECKCAST, p_type.getDescriptor()); break; case Type.OBJECT: mv.visitTypeInsn(CHECKCAST, p_type.getInternalName()); break; } buf.append(p_type.getDescriptor()); } buf.append(')').append(Type.getDescriptor(returnType)); // ??, ??? if (isInterface) { mv.visitMethodInsn(INVOKEINTERFACE, classNameInternal, methodNames[i], buf.toString(), true); } else if (Modifier.isStatic(methods.get(i).getModifiers())) { mv.visitMethodInsn(INVOKESTATIC, classNameInternal, methodNames[i], buf.toString(), false); } else { mv.visitMethodInsn(INVOKEVIRTUAL, classNameInternal, methodNames[i], buf.toString(), false); } Type r_type = Type.getType(returnType); switch (r_type.getSort()) { case Type.VOID: mv.visitInsn(ACONST_NULL); break; case Type.BOOLEAN: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); break; case Type.BYTE: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false); break; case Type.CHAR: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false); break; case Type.SHORT: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false); break; case Type.INT: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); break; case Type.FLOAT: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false); break; case Type.LONG: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false); break; case Type.DOUBLE: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false); break; } mv.visitInsn(ARETURN); } mv.visitLabel(defaultLabel); // default ?? mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); } // throw exception (method not found) 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", false); mv.visitVarInsn(ILOAD, 2); 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(); } cw.visitEnd(); byte[] bytes = cw.toByteArray(); AccessorClassLoader loader = AccessorClassLoader.get(type); Class<?> accessorClass = loader.defineClass(accessorClassName, bytes); try { FastMethodAccessor accessor = (FastMethodAccessor) accessorClass.newInstance(); accessor.methodNames = methodNames; accessor.parameterTypes_s = parameterTypes_s; return accessor; } catch (Throwable t) { throw new RuntimeException("Error constructing method access class: " + accessorClass, t); } }