List of usage examples for org.objectweb.asm MethodVisitor visitTableSwitchInsn
public void visitTableSwitchInsn(final int min, final int max, final Label dflt, final Label... labels)
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(); }