6

I want to write a simple java agent which can print the name of a method called by the java program instrumented.

For example, my java program I want to instrument is:

public class TestInstr {

public static void sayHello() {
    System.out.println("Hello !");
}

public static void main(String args[]) {
    sayHello();
    sayHello();
    sayHello();
 }

}

I would like to display something like this :

method sayHello has been called
Hello !
method sayHello has been called
Hello !
method sayHello has been called
Hello !

Thanks for your help!

4

5 回答 5

11

您可以使用诸如 Javassist 之类的检测库来执行此操作。

让我给你一个单一方法的例子,你可以使用 Javassist 或反射将它扩展到所有方法:

ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("TestInstr");
CtMethod m = cc.getDeclaredMethod("sayHello");
m.insertBefore("{ System.out.println(\"method sayHello has been called\"); }");
cc.writeFile();

详情请查看此链接:http ://www.csg.ci.iu-tokyo.ac.jp/~chiba/javassist/tutorial/tutorial2.html#intro

于 2012-05-18T21:04:50.257 回答
4

我似乎记得AspectJ可以做这样的事情;然而,我没有这方面的经验,所以探索可能性取决于你!:D

于 2012-05-18T20:58:37.107 回答
1

在您可以添加的方法中

public class TestInstr {

public static void sayHello() {
System.out.println("method sayHello has been called");
System.out.println("Hello !");
}

public static void main(String args[]) {
sayHello();
sayHello();
sayHello();
}
}

您可以使用它来获取当前方法

public String getCurrentMethodName() {
 StackTraceElement stackTraceElements[] =
         (new Throwable()).getStackTrace();
 return stackTraceElements[1].toString();
}

我不确定这是否是你要找的。

于 2012-05-18T20:58:11.123 回答
1

我不认为这很容易。

我能想到的唯一选择是实现类加载器并用您创建的存根替换原始类(Hibernate / JPA 为延迟加载做了类似的事情)。存根将执行您需要的操作,然后调用原始类来执行工作。这将意味着沉重的负担(反射调用并不便宜)。

于 2012-05-18T20:59:06.863 回答
0

如果您的需要只是记录一个方法是否被调用,那么面向方面的编程正是您所需要的,无论是 AspectJ(静态)还是 Spring AOP(动态),都提供了强大的功能来做到这一点。但是,您可能需要一些仪器库,以防您想做更多的仪器工作,例如跟踪执行时间、调用 track. 希望能帮助到你。

于 2014-10-22T04:02:32.810 回答