NutzCN Logo
问答 FastMethodFactory如何给类添加invoke方法体
发布于 2748天前 作者 tiankongkm 1594 次浏览 复制 上一个帖子 下一个帖子
标签:

以前看这块的源码。好像没用asm,直接method.invoke(module, args)的,
然后今天再看下,用了FastMethod.invoke(module, args) 来执行 瞬间糟逼了,,,
请问下大大 下面那块代码 GeneratorAdapter 生成invoke方法后如何添加的方法内容。。还用这里用asm给每个方法都生成一个新的类有啥好处吗。。。

public void process(ActionContext ac) throws Throwable {
        Object module = ac.getModule();
        Method method = ac.getMethod();
        Object[] args = ac.getMethodArgs();
        try {
        	if (Mvcs.disableFastClassInvoker)
        		ac.setMethodReturn(method.invoke(module, args));
        	else {
        	    _check(method);
        		ac.setMethodReturn(fm.invoke(module, args));
        	}
            doNext(ac);
        } 
}
 public static byte[] _make(Class<?> klass,
                               int mod,
                               Class<?>[] params,
                               org.nutz.repo.org.objectweb.asm.commons.Method method,
                               Class<?> returnType,
                               String className,
                               String descriptor) {
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
        cw.visit(V1_5,
                 ACC_PUBLIC,
                 className.replace('.', '/'),
                 null,
                 "java/lang/Object",
                 new String[]{FastMethod.class.getName().replace('.', '/')});
        
        Type klassType = Type.getType(klass);

        // 首先, 定义默认构造方法
        addConstructor(cw, Type.getType(Object.class), org.nutz.repo.org.objectweb.asm.commons.Method.getMethod("void <init> ()"));

        // 然后定义执行方法
        GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, _M, null, new Type[]{Exception_TYPE}, cw);
        if (returnType == null) {
            mg.newInstance(klassType);
            mg.dup();
        }
        else if (!Modifier.isStatic(mod)) {
            mg.loadThis();
            mg.loadArg(0);
            mg.checkCast(klassType);
        }
        if (params.length > 0) {
            for (int i = 0; i < params.length; i++) {
                mg.loadArg(1);
                mg.push(i);
                mg.arrayLoad(Type.getType(Object.class));
                Type paramType = Type.getType(params[i]);
                if (params[i].isPrimitive()) {
                    mg.unbox(paramType);
                } else {
                    mg.checkCast(paramType);
                }
            }
        }
        if (returnType == null) {
            mg.invokeConstructor(klassType, method);
        } else {
            if (Modifier.isStatic(mod)) {
                mg.invokeStatic(klassType, method);
            } else if (Modifier.isInterface(klass.getModifiers())) {
                mg.invokeInterface(klassType, method);
            } else {
                mg.invokeVirtual(klassType, method);
            }
            if (Void.class.equals(returnType)) {
                mg.visitInsn(ACONST_NULL);
            } else if (returnType.isPrimitive()) {
                mg.box(Type.getType(returnType));
            }
        }
        Label tmp = new Label();
        mg.visitLabel(tmp);
        mg.visitLineNumber(1, tmp);
        mg.returnValue();
        mg.endMethod();
        cw.visitSource(klass.getSimpleName() + ".java", null);
        cw.visitEnd();
        return cw.toByteArray();
    }
5 回复

以前是asm, 现在也是asm.

区别在于, 之前用asm的裸api, 现在用asm commons里面的GeneratorAdapter 稍微简化一下.

至于 "用asm给每个方法都生成一个新的类有啥好处" 减少了反射的调用,简单来说就是能装逼.

@wendal 新生成的类里的invoke内容是啥,,哪句代码添加的。

哦? 你想理解这个make方法? 我加点注释吧

恩恩,谢兽总!!!!23333

好了,提交了

添加回复
请先登陆
回到顶部