I am trying to instrument java class through attach
API ( I want to instrument java.sql.DriverManager.getConnection()
method specifically and record the returning Connection
object).
So , I am doing the store and load operations and calling up a method defined in one of my class ( say , foo.TestRecordingClass.myFooRecordingMethod()
) .
Now , my problem is that whenever I am trying to call the method mentioned earlier ( through attach API : agentmain
is called ) , I am getting a NoClassDefFoundError
.
But , the same thing instruments perfectly with premain
, a.k.a Xbootclasspath
approach .
Thanks in advance :-)
Ok , I am able to solve the problem using appendToBootstrapClassLoaderSearch(JarFile)
method of instrumentation
object.
Now , one more problem I am facing , which is loading one this
object onto stack.
Theoretically , if I do aload_0
operation , that should load the current object , then I can pass it to any method , right ?
In the method visitInsn
( i.e while returning from method ) , I am doing this :
super.visitVarInsn(Opcodes.ALOAD, 0);
super.visitMethodInsn(Opcodes.INVOKESTATIC, fooClassName, "fooMethodReturnInstrumentor", "(Ljava/lang/Object;)V");
This should load the object itself , but I am not able to retrieve anything.
If you instrument a class and insert new references to other classes these classes must be accessible by the instrumented class which includes that resolving it via its ClassLoader
must succeed (compare to this answer) and it must either reside in the same package
or have public
access modifier. This answer contains some remarks about instrumenting core Java classes.
So if your foo.TestRecordingClass
is public
and added to the bootstrap class path, it can be accessed by any instrumented class.
The first variable contains this
only if the method is not static
, and not a constructor. In the latter case, the first variable contains an uninitialized this which cannot be passed to a method invocation before the super constructor has been called.
On the other hand, this assignment is only fixed for the beginning of the method. Within the method, the variable might get reused for other purposes and even become invalid if two branch paths using it for different purposes join.
So, at the beginning of an instance method which is not a constructor you can indeed put an aload_0
followed by an invokestatic
consuming one object, to pass this
to the method. Your “I am not able to retrieve anything” problem description is a bit thin. If your method is never called, this might be a simple sign that the instrumented code is never invoked. If you receive null
, it is a strong indicator that the first variable does not contain this
. Then, verify whether your inserted invocation is really at the beginning of an instance method.
If you want to place the invocation at a different place you have to check that variable 0 is never overwritten before the method call.