Antlr是跟踪带有参数名称和值的Java方法调用并返回结果的正确工具吗?



我想打印出带有参数名称和值的Java方法调用,并返回结果。

我不想手动添加跟踪语句,特别是当代码在第三方库中时。我需要了解与库的交互,特别是当使用回调时。

我尝试使用包装器,但遇到了问题,所以子类化是更好的。(即wrappedoobject . methoda()或super.methodA()调用)

写这段代码很痛苦,尤其是当有很多方法的时候。

我希望Java可以自动完成这个任务,因为它有一切使这成为可能。

最好的方法是什么?用包装器或子类替换对象是一种折衷。

因此,下一步是将跟踪代码添加到包装器或子类中。我想写一个解析器来生成代码。

我已经使用了yacc &我刚发现了Antlr。

Antlr是做这件事的正确工具吗?请问我该怎么做?我以前没有使用过Antlr,但在周围见过。

谢谢。

这是我想做的-

// 3rdParty library under investigation, with evolving versions
import com.3rdParty.lib.Service;
import com.3rdParty.lib.Callback;
MyExistingClass {
    Service service = new Service();
    // Need to understand 3rd party library service and callback interactions
    // Also need to write my own callbacks using 3rd party interface
    if (traceMethod1) {
      service.doSomething(param1, new CallbackWrapper(), param3);
    }
    else if (traceMethod2) {
      service.doSomething(param1, new CallbackSubclass(), param3);
    }
    else {
      // Original code
      // Service calls Callback methods
      service.doSomething(param1, new Callback(), param3);
    }
}
--------------------------------------------------------------------------------
// 3rd Party code - Service calls Callback methods
package com.3rdParty.lib;
public Callback extends SomeBaseClass {
    public void methodA(int code, String action, SomeClass data) {
        // do method A stuff
    }
    public String methodB(String name, boolean flag) {
        // do method B stuff
        return result;
    }
    ...etc.
}
--------------------------------------------------------------------------------
// Wrapper class - traceMethod1
package com.my.package;
import com.3rdParty.lib.Callback;
public CallbackWrapper implements SomeCallbackInterface {
    Callback cb = new Callback();
    public void methodA(int code, String action, SomeClass data) {
        logger.debug("CallbackWrapper.methodA() called");
        logger.debug("  code = " + code);
        logger.debug("  action = " + action);
        logger.debug("  data = " + data);
        cb.methodA(code, action, data);
        logger.debug("CallbackWrapper.methodA() returns");
    }
    public String methodB(String name, boolean flag) {
        logger.debug("CallbackWrapper.methodB() called");
        logger.debug("  name = " + name);
        logger.debug("  flag = " + flag);
        String result = cb.methodB(name, flag);
        logger.debug("CallbackWrapper.methodB() returns result = " + result);
        return result;
    }
    ...etc.
}
--------------------------------------------------------------------------------
// Subclass - traceMethod2
package com.my.package;
import com.3rdParty.lib.Callback;
public CallbackSubclass extends Callback {
    public void methodA(int code, String action, SomeClass data) {
        logger.debug("CallbackSubclass.methodA() called");
        logger.debug("  code = " + code);
        logger.debug("  action = " + action);
        logger.debug("  data = " + data);
        super.methodA(code, action, data);
        logger.debug("CallbackSubclass.methodA() returns");
    }
    public String methodB(String name, boolean flag) {
        logger.debug("CallbackSubclass.methodB() called");
        logger.debug("  name = " + name);
        logger.debug("  flag = " + flag);
        String result = super.methodB(name, flag);
        logger.debug("CallbackSubclass.methodB() returns result = " + result);
        return result;
    }
    ...etc.
}

在Java中做这类事情最简单的方法是使用字节码而不是源代码。使用BCEL (https://commons.apache.org/proper/commons-bcel/)或ASM (http://asm.ow2.org/),您可以动态地创建和加载现有类的修改版本,甚至是从头生成的全新类。

这仍然不容易,但比尝试进行源代码翻译要容易得多。

对于跟踪方法调用的特殊问题,您可以创建一个自定义ClassLoader,它可以用自定义跟踪代码自动检测它加载的每个类中的每个方法。

ANTLR不是合适的工具。虽然您可以获得用于构建ast的ANTLR的Java语法,但ANTLR在修改ast或重新生成可编译的源文本方面不会提供太多帮助。

你需要的是一个程序转换系统(PTS)。这些工具可以解析源代码,构建ast,为您提供通过源到源转换修改这些ast的方法,并且可以从修改过的树中重新生成可编译的源文本。

PTS的源到源转换通常根据要转换的语言语法(在本例中为java)编写:
      if you see *this*, replace it by *that* if some *condition*

我们的DMS软件再造工具包就是这样一个具有可用Java前端的PTS。

你想做的很像插装代码;只需修改受害者方法,使其执行所需的跟踪即可。请参阅分支覆盖变得简单的示例,了解我们如何使用这种源代码到源代码的重写来实现Java的插装工具。

或者,您可以编写规则,将受害者类和方法复制为子类,并按照您所建议的那样连接跟踪。检测可能比复制所有东西更容易。(当然,当你在编写转换规则时,你真的不关心代码改变了多少,因为在你的情况下,你会在完成它后把它扔掉;你在乎写规则要花多少精力]

参见DMS重写规则,详细讨论了这些规则的真正样子,以及重写规则对源代码进行更改的工作示例。

其他人建议对编译的字节码进行转换。是的,它的工作原理与PTS系统的工作原理相同,但是您需要手工编写代码,并且转换是由一堆在JVM指令上操作的过程性代码编写的,仅凭人类是无法读取的。在没有其他选择的情况下,我理解人们采取这种方法。我的主要观点是是有选择的

最新更新