检测Java匿名内部类对象

时间:2012-02-10 14:22:24

标签: java bytecode instrumentation

所以,给出以下代码:

public MyInterface getMyInterface() {
    return new MyInterface() {
        public SomethingElse getSomethingElse() {
           // ....
        }
    }
}

...
MyInterface obj = getMyInterface();

有没有办法对obj上的getSomethingElse()进行调用?进去做一些字节码修改或什么?

我在那里有生产代码,在不同的情况下(称之为“设计时”)我想添加一些跟踪/记录和这样的代码以帮助进行故障排除和分析。性能对于生产情况至关重要,因此我希望在没有额外跟踪/日志记录开销的情况下保留它。但在设计时间情况下,我希望获得所有跟踪信息。

3 个答案:

答案 0 :(得分:1)

如果要在开发中打开登录,最简单的方法是

if(LOGGER.isDebugEnabled())
   LOGGER.debug("my debug message");

增加的头数是亚纳秒,所以即使您正在使用每纳秒计数的系统,这仍然是最好的模式。


你可以用

来上课
 Class.forName("package.OuterClass$NNN");

您需要调用一个构造函数,该构造函数接受外部类的实例。

答案 1 :(得分:1)

是的,有可能做你所要求的,虽然肯定有更好的方法来实现它 - 最明显的是创建MyInterface的默认实现,然后扩展它的“跟踪”子类和调用超类版本之前的日志。

如果检测是您唯一的选择,那么在设计时运行时,您可以使用Java 5中的Java代理启动项目,或者在Java 6中在运行时将java代理添加到类路径中。请参阅instrumentation documentation

要修改课程,您可能需要使用ASM之类的工具。步骤将是这样的:

  1. 在您的Agent类中,实现java.lang.instrument.ClassFileTransformer。
  2. 在agentmain()或premain()方法中,request转换类。
  3. 当您收到对transform方法的调用时,可以使用Class.getInterfaces()检查该类是否实现了MyInterface。
  4. 您可以选择查看其Class.getEnclosingClass()是否是您编写/找到此代码的类。
  5. 如果Class通过了这些健全性检查,则创建一个ClassWriter,将日志记录添加到getSomethingElse()方法。在尝试找出如何生成所需代码时,ASMifier会有很大帮助。
  6. 然后,在生产中,这些代码都不存在。在开发过程中,您可以在您的环境中添加Java代理,从而实现调试。

    同样,几乎肯定有更好的方法可以做到这一点,但是有充分的理由使用仪器,这是一个迷你速成课程。

    希望有所帮助,

答案 2 :(得分:-1)

这听起来像是使用aspects的好例子。

您可以简单地在测试环境中的任何方法周围应用日志记录/跟踪代码,并在迁移到生产环境时将其遗漏。