在运行时调用Wrap方法

时间:2015-01-23 13:46:00

标签: java

有哪些技术可用并建议在运行时动态包装方法调用?例如,假设我想用一些时序信息包含对方法foo()的调用,而不需要用户根本改变代码。

2 个答案:

答案 0 :(得分:1)

您是否查看了java.lang.reflect.Proxy的接口或cglib的类。

希望它有所帮助。

答案 1 :(得分:1)

如果要在应用程序的任何位置包装调用,可以考虑编写一个简单的JavaAgent。然后,您可以使用Javassist在调用方法之前和/或之后调用某个方法。以下示例广告跟踪调用给定类的所有方法。

import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;

public class MethodTraceTransformer implements ClassFileTransformer {

    public byte[] transform(ClassLoader loader, String className,
        Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
        byte[] classfileBuffer) throws IllegalClassFormatException {

        byte[] byteCode = classfileBuffer;

        if (className.equals("<The class you want to instrument>")) {
            try {
                byteCode = addTracer(className.replace("/", "."));
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }

        return byteCode;
    }

    private byte[] addTracer(String classname) throws NotFoundException,
        CannotCompileException, IOException {
        CtClass clazz = ClassPool.getDefault().get(classname);

        CtMethod[] methods = clazz.getDeclaredMethods();
        for (CtMethod c : methods) {
            c.insertBefore(TraceLogger.class.getName()
                    + ".get().logTrace($args);");
        }

        byte[] byteCode = clazz.toBytecode();
        clazz.detach();
        return byteCode;
    }
}

您可以在此处找到更详尽的教程:http://blog.javabenchmark.org/2013/05/java-instrumentation-tutorial.html

如果您只想测量方法的执行时间,可能更容易使用AspectJ之类的东西:http://www.pabloguerrero.org/cgblog/9/15/Monitor-Java-methods-memory-usage-and-execution-time-with-AspectJ