【问题标题】:Instrumenting Java classes through attach API通过附加 API 检测 Java 类
【发布时间】:2014-09-22 06:26:40
【问题描述】:

我正在尝试通过 attach API 检测 java 类(我想专门检测 java.sql.DriverManager.getConnection() 方法并记录返回的 Connection 对象)。

所以,我正在执行存储和加载操作并调用在我的一个类中定义的方法(例如,foo.TestRecordingClass.myFooRecordingMethod())。

现在,我的问题是,每当我尝试调用前面提到的方法时(通过附加 API:agentmain 被调用),我都会得到一个NoClassDefFoundError

但是,同样的东西可以完美地使用 premain ,也就是 Xbootclasspath 方法。

提前致谢:-)

编辑1:

好的,我可以使用instrumentation对象的appendToBootstrapClassLoaderSearch(JarFile)方法解决问题。

现在,我面临的另一个问题是将一个this 对象加载到堆栈上。

理论上,如果我做aload_0操作,那应该加载当前对象,然后我可以将它传递给任何方法,对吧?

visitInsn 方法中(即从方法返回时),我正在这样做:

super.visitVarInsn(Opcodes.ALOAD, 0); super.visitMethodInsn(Opcodes.INVOKESTATIC, fooClassName, "fooMethodReturnInstrumentor", "(Ljava/lang/Object;)V");

这应该加载对象本身,但我无法检索任何内容。

【问题讨论】:

    标签: java bytecode instrumentation java-bytecode-asm


    【解决方案1】:

    如果您检测一个类并插入对其他类的新引用,则这些类必须可由检测类访问,包括通过其ClassLoader 解析它必须成功(与this answer 相比)并且它必须驻留在相同的package 或具有public 访问修饰符。 This answer 包含一些关于检测核心 Java 类的评论。

    因此,如果您的 foo.TestRecordingClasspublic 并添加到引导类路径,则任何检测类都可以访问它。

    只有当方法不是static,而不是构造函数时,第一个变量才包含this。在后一种情况下,第一个变量包含一个 未初始化的 this,它在调用超级构造函数之前无法传递给方法调用。

    另一方面,这个赋值只在方法的开始是固定的。在该方法中,该变量可能会被重复用于其他目的,如果两条用于不同目的的分支路径连接起来,该变量甚至会变得无效。

    因此,在不是构造函数的实例方法的开头,您确实可以在 aload_0 之后放置一个使用一个对象的 invokestatic,以将 this 传递给该方法。您的“我无法检索任何东西”的问题描述有点单薄。如果您的方法从未被调用,这可能是一个简单的迹象,表明从未调用过检测代码。如果您收到null,则强烈指示第一个变量不包含this。然后,验证您插入的调用是否真的在实例方法的开头。

    如果你想将调用放在不同的地方,你必须检查变量 0 在方法调用之前永远不会被覆盖。

    【讨论】:

    • 感谢您的回复。我故意更改了visitMethodInsn 签名/没有加载参数。在这两种情况下,我都得到了验证错误,这意味着指令正在被调用。但是,每当我尝试加载恒定值(ldc)时,什么都没有发生..
    • 好吧,如果你不加载一个值到栈中,你就不能调用一个有参数/消耗一个对象的方法。但是获得VerifierError 并不是一个安全的信号,表明代码会被调用。 JVM 可能会在类加载或方法入口上验证代码,这两者并不意味着会调用特定指令。
    • 非常感谢您的快速回复。你真的是一个救生员。但是,我仍然面临这个问题。让我详细解释一下我的问题:我想跟踪 JDBC 连接何时关闭。因此,为此我需要检测实现 Connection 的类。而在close() 方法的返回块中,我想检测一些东西(比如一些常量值)。如果我收到了一些讨厌的 verfier error ,事情对我来说会一帆风顺。但是,到目前为止,我还在摸不着头脑,什么也没有发生
    • 重命名原始close 方法并插入一个调用重命名的原始方法并执行后操作的新方法更容易。因此,您不必处理原始 close 方法的未知、可能非常复杂的结构。
    • 你确实是个摇滚明星。让我试一次。如有任何问题,会尽快回复您(希望我不会太烦您:-))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-14
    • 2011-06-23
    • 1970-01-01
    • 2015-03-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多