/** 用于更新类名。 */ public void visit( final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) { // 1.类名 this.superClassName = name; String className = this.classConfig.getClassName(); className = classConfig.getClassName().replace(".", "/"); // 2.确定接口 Set<String> newFaces = new HashSet<String>(); for (String faces : interfaces) { newFaces.add(faces); } InnerMethodDelegateDefine[] defineArrays = this.classConfig.getNewDelegateList(); for (InnerMethodDelegateDefine define : defineArrays) { Class<?> faceType = define.getFaces(); newFaces.add(ASMEngineTools.replaceClassName(faceType)); } String[] finalInterfaces = newFaces.toArray(new String[newFaces.size()]); // super.visit(version, access, className, signature, name, finalInterfaces); }
private void visitConstruction(MethodVisitor mv, String name, String desc) { // 1.准备输出方法数据 Pattern p = Pattern.compile("\\((.*)\\)(.*)"); Matcher m = p.matcher(desc); m.find(); String[] asmParams = ASMEngineTools.splitAsmType( m.group(1)); // "IIIILjava/lang/Integer;F[[[ILjava/lang.Boolean;" int paramCount = asmParams.length; // mv.visitVarInsn(ALOAD, 0); for (int i = 0; i < paramCount; i++) { String asmType = asmParams[i]; mv.visitVarInsn(ASMEngineTools.getLoad(asmType), i + 1); } mv.visitMethodInsn(INVOKESPECIAL, this.superClassName, name, desc); mv.visitInsn(RETURN); mv.visitMaxs(paramCount + 1, paramCount + 1); }
public void visitEnd() { InnerMethodDelegateDefine[] defineArrays = this.classConfig.getNewDelegateList(); for (InnerMethodDelegateDefine define : defineArrays) { Class<?> faceType = define.getFaces(); Method[] faceMethods = faceType.getMethods(); for (Method tMethod : faceMethods) { String mName = tMethod.getName(); String typeDesc = String.format("%s(%s)", mName, ASMEngineTools.toAsmType(tMethod.getParameterTypes())); // if (this.validMethod.contains(typeDesc) == false) { String desc = ASMEngineTools.toAsmDesc(tMethod); MethodVisitor mv = super.visitMethod(ACC_PUBLIC, mName, desc, null, null); mv.visitCode(); this.buildInterfaceMethod(mv, mName, desc, faceType); mv.visitEnd(); } // } // } super.visitEnd(); }
// Code Builder “return ...” private void codeBuilder_3(MethodVisitor mv, String asmReturns) { if (asmReturns.equals("B") == true) { mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Byte"); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B"); mv.visitInsn(ASMEngineTools.getReturn("B")); } else if (asmReturns.equals("S") == true) { mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Short"); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S"); mv.visitInsn(ASMEngineTools.getReturn("S")); } else if (asmReturns.equals("I") == true) { mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Integer"); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I"); mv.visitInsn(ASMEngineTools.getReturn("I")); } else if (asmReturns.equals("J") == true) { mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Long"); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J"); mv.visitInsn(ASMEngineTools.getReturn("J")); } else if (asmReturns.equals("F") == true) { mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Float"); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F"); mv.visitInsn(ASMEngineTools.getReturn("F")); } else if (asmReturns.equals("D") == true) { mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Double"); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D"); mv.visitInsn(ASMEngineTools.getReturn("D")); } else if (asmReturns.equals("C") == true) { mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Character"); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C"); mv.visitInsn(ASMEngineTools.getReturn("C")); } else if (asmReturns.equals("Z") == true) { mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Boolean"); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z"); mv.visitInsn(ASMEngineTools.getReturn("Z")); } else if (asmReturns.equals("V") == true) { mv.visitInsn(Opcodes.POP); mv.visitInsn(Opcodes.RETURN); } else { mv.visitTypeInsn(Opcodes.CHECKCAST, ASMEngineTools.asmTypeToType(asmReturns)); mv.visitInsn(Opcodes.ARETURN); } }
// // Code Builder “new Object[] { abc, abcc, abcc };” private void codeBuilder_1(MethodVisitor mv, String[] asmParams) { int paramCount = asmParams.length; mv.visitIntInsn(Opcodes.BIPUSH, paramCount); mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); for (int i = 0; i < paramCount; i++) { String asmType = asmParams[i]; mv.visitInsn(Opcodes.DUP); mv.visitIntInsn(Opcodes.BIPUSH, i); if (asmParams[i].equals("B") == true) { mv.visitVarInsn(ASMEngineTools.getLoad(asmType), i + 1); mv.visitMethodInsn( Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;"); } else if (asmParams[i].equals("S") == true) { mv.visitVarInsn(ASMEngineTools.getLoad(asmType), i + 1); mv.visitMethodInsn( Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;"); } else if (asmParams[i].equals("I") == true) { mv.visitVarInsn(ASMEngineTools.getLoad(asmType), i + 1); mv.visitMethodInsn( Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;"); } else if (asmParams[i].equals("J") == true) { mv.visitVarInsn(ASMEngineTools.getLoad(asmType), i + 1); mv.visitMethodInsn( Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;"); } else if (asmParams[i].equals("F") == true) { mv.visitVarInsn(ASMEngineTools.getLoad(asmType), i + 1); mv.visitMethodInsn( Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;"); } else if (asmParams[i].equals("D") == true) { mv.visitVarInsn(ASMEngineTools.getLoad(asmType), i + 1); mv.visitMethodInsn( Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;"); } else if (asmParams[i].equals("C") == true) { mv.visitVarInsn(ASMEngineTools.getLoad(asmType), i + 1); mv.visitMethodInsn( Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;"); } else if (asmParams[i].equals("Z") == true) { mv.visitVarInsn(ASMEngineTools.getLoad(asmType), i + 1); mv.visitMethodInsn( Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;"); } else { mv.visitVarInsn(Opcodes.ALOAD, i + 1); } mv.visitInsn(Opcodes.AASTORE); } }
// 实现接口附加 private void buildInterfaceMethod(MethodVisitor mv, String name, String desc, Class<?> faceType) { // 例子代码 // public int getNames(int abc, Object abcc) { // try { // Class<?>[] arrayOfClass = new Class[] { int.class, Object.class }; // Object[] arrayOfObject = new Object[] { abc, abcc }; // // // Method localMethod = List.class.getMethod("getNames", arrayOfClass); // ClassLoader localLoader = getClass().getClassLoader(); // // // Object target = new InnerChainMethodDelegate("xxxx", // localLoader).invoke(localMethod, this, arrayOfObject); // return ((Integer) target).intValue(); // } catch (Throwable e) { // throw new RuntimeException(e); // } // } // 1.准备输出方法数据 Pattern p = Pattern.compile("\\((.*)\\)(.*)"); Matcher m = p.matcher(desc); m.find(); String[] asmParams = ASMEngineTools.splitAsmType( m.group(1)); // "IIIILjava/lang/Integer;F[[[ILjava/lang.Boolean;" String asmReturns = m.group(2); int paramCount = asmParams.length; int maxStack = 4; // 方法最大堆栈大小 int maxLocals = paramCount + 5; // 本地变量表大小 // Label tryBegin = new Label(); Label tryEnd = new Label(); Label tryCatch = new Label(); mv.visitTryCatchBlock(tryBegin, tryEnd, tryCatch, "java/lang/Throwable"); { // try { mv.visitLabel(tryBegin); // Class<?>[] pTypes = new Class[] { int.class, Object.class, boolean.class, short.class }; this.codeBuilder_2(mv, asmParams); mv.visitVarInsn(ASTORE, paramCount + 2); // Object[] pObjects = new Object[] { abc, abcc, abcc }; this.codeBuilder_1(mv, asmParams); mv.visitVarInsn(ASTORE, paramCount + 3); // // List.class.getMethod("getNames", arrayOfClass); mv.visitLdcInsn(Type.getType(ASMEngineTools.toAsmType(faceType))); mv.visitLdcInsn(name); mv.visitVarInsn(ALOAD, paramCount + 2); mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;"); mv.visitVarInsn(ASTORE, paramCount + 4); // // ClassLoader localLoader = getClass().getClassLoader(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;"); mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getClassLoader", "()Ljava/lang/ClassLoader;"); mv.visitVarInsn(ASTORE, paramCount + 5); // // Object target = new InnerChainMethodDelegate("xxxx", localLoader).invoke(localMethod, this, // arrayOfObject); mv.visitTypeInsn(NEW, ASMEngineTools.replaceClassName(InnerChainMethodDelegate.class)); mv.visitInsn(DUP); mv.visitLdcInsn(this.classConfig.getClassName()); mv.visitLdcInsn(faceType.getName()); mv.visitVarInsn(ALOAD, paramCount + 5); mv.visitMethodInsn( INVOKESPECIAL, ASMEngineTools.replaceClassName(InnerChainMethodDelegate.class), "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V"); mv.visitVarInsn(ALOAD, paramCount + 4); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, paramCount + 3); mv.visitMethodInsn( INVOKEVIRTUAL, ASMEngineTools.replaceClassName(InnerChainMethodDelegate.class), "invoke", "(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"); mv.visitVarInsn(ASTORE, paramCount + 6); // // return mv.visitVarInsn(ALOAD, paramCount + 6); mv.visitLabel(tryEnd); this.codeBuilder_3(mv, asmReturns); } { // } catch (Exception e) { mv.visitLabel(tryCatch); mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/Throwable"}); mv.visitVarInsn(ASTORE, 5); mv.visitVarInsn(ALOAD, 5); mv.visitTypeInsn(INSTANCEOF, "java/lang/RuntimeException"); Label ifBlock = new Label(); mv.visitJumpInsn(IFEQ, ifBlock); mv.visitVarInsn(ALOAD, 5); mv.visitTypeInsn(CHECKCAST, "java/lang/RuntimeException"); mv.visitInsn(ATHROW); mv.visitLabel(ifBlock); mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] {"java/lang/Throwable"}, 0, null); mv.visitTypeInsn(NEW, "java/lang/RuntimeException"); mv.visitInsn(DUP); mv.visitVarInsn(ALOAD, 5); mv.visitMethodInsn( INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/Throwable;)V"); mv.visitInsn(ATHROW); mv.visitMaxs(maxStack, maxLocals); } // } }