通过附加API检测Java类

通过附加API检测Java类,java,bytecode,instrumentation,java-bytecode-asm,Java,Bytecode,Instrumentation,Java Bytecode Asm,我试图通过attachAPI插入java类(我想专门插入java.sql.DriverManager.getConnection()方法,并记录返回的Connection对象) 因此,我正在执行存储和加载操作,并调用在我的一个类中定义的方法(例如,foo.TestRecordingClass.myfoorrecordingmethod()) 现在,我的问题是,每当我试图调用前面提到的方法时(通过attach API:agentmain被调用),我都会得到一个NoClassDefFoundErro

我试图通过
attach
API插入java类(我想专门插入
java.sql.DriverManager.getConnection()
方法,并记录返回的
Connection
对象)

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

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

但是,同样的东西在
premain
,也就是Xbootclasspath方法中完美地插入

提前感谢:-)

编辑1: 好的,我可以使用
appendToBootstrapClassLoaderSearch(JarFile)
methodof
instrumentation
object解决这个问题

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

理论上,如果我执行
aload_0
操作,应该加载当前对象,那么我可以将其传递给任何方法,对吗

在方法
visitInsn
(即从方法返回时)中,我执行以下操作:

super.visitVarInsn(opcode.ALOAD,0);
super.visitMethodInsn(opcode.INVOKESTATIC,fooClassName,“fooMethodReturnInstrumentor”,“Ljava/lang/Object;)V)


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

如果插入一个类并插入对其他类的新引用,这些类必须能够被插入类访问,包括通过其
类加载器
解析它必须成功(与)并且它必须位于相同的
包中
,或者具有
公共
访问修饰符。包含一些关于检测核心Java类的注释

因此,如果您的
foo.TestRecordingClass
public
并添加到引导类路径,则任何插入指令的类都可以访问它

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

另一方面,此赋值仅在方法开始时固定。在该方法中,该变量可能会被重用用于其他目的,甚至在两个用于不同目的的分支路径连接时变得无效

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


如果要将调用放置在其他位置,则必须检查变量0在方法调用之前是否从未被覆盖。

谢谢您的回复。我故意更改了
visitMethodInsn
签名/没有加载参数。在这两种情况下,我都得到了verifyerror,这意味着指令正在被调用。但是,每当我尝试加载常量值时(通过
ldc
),都不会发生任何事情。好吧,如果不将值加载到堆栈中,就不能调用具有参数/使用一个对象的方法。但是获得
验证错误
并不是调用代码的安全标志。JVM可能会在类加载或方法项上验证代码,这两种情况都不意味着会调用特定的指令。非常感谢您的快速回复。你真是个救命恩人。但是,我仍然面临着这个问题。让我详细解释我的问题:我想跟踪
JDBC
连接何时关闭。因此,为此,我需要为实现
连接的类插入指令。在
close()
方法的返回块中,我想插入一些东西(比如一些常量值)。如果我收到了一些严重的错误,事情就会一帆风顺。但是,到目前为止,我还在挠头,什么也没有出现。重命名原始的
close
方法并插入一个新方法更容易,该方法调用重命名的原始方法并执行post操作。因此,您不必处理原始
close
方法的未知、可能非常复杂的结构。您确实是一个摇滚明星。让我试一下。如果有任何问题,我会回复你(我希望我没有太烦你:-)