I need to know the name of the object which called invokevirtual operation(in the following format - Objectname@object_id). Is it possible given only MethodInsnNode object? I know that it is stored with the index 0 in local variables but I don't know how to get it.
-
I'm not entirely sure what you're talking about. For local variables, for example, the names are not stored (except in debugging information). Can you post an example of what the code would look like and what information you'd need about it? Also: is this about static analysis or during runtime? – Joachim Sauer Sep 03 '12 at 12:01
-
Do you need to get that "object name" at runtime or during some kind of off-line static analysis phase? Also, what have you tried? BTW, generally it is NOT necessarily stored in local var 0. – Eugene Kuleshov Sep 05 '12 at 15:37
-
I need object name at runtime. I don't know how to get method local variables – Sergey Sep 06 '12 at 08:20
2 Answers
You need the MethodNode to get access to the local variables.
If you have the associated MethodNode in the variable mn
and your MethodInsnNode stored in insn
then:
InsnList insnList = mn.instructions;
int instructionIdx = insnList.indexOf(insn);
String name = null;
int wantedLocalVariableIndex = 0;
for (LocalVariableNode lvn : mn.localVariables) {
if (lvn.index == wantedLocalVariableIndex && insnList.indexOf(lvn.start) < instructionIdx && instructionIdx < insnList.indexOf(lvn.end)) {
name = lvn.name;
break;
}
}
if (name != null) {
// we found it's name
}

- 3,344
- 1
- 27
- 33
-
Aren't the conditions `insnList.indexOf(lvn.start) < instructionIdx && instructionIdx < insnList.indexOf(lvn.end)` redundant? Is it possible to have a local variable node in which `lvn.index == 0` which does not represent `this` (in an instance method invocation)? Also, shouldn't `insnList.indexOf(lvn.start) < instructionIdx` be `<=`? According to the Javadoc of `LocalVariableNode.start` : "The first instruction corresponding to the scope of this local variable (inclusive)." – rapt Mar 29 '19 at 02:10
-
-
"The array of local variables, also called the local variable table, contains the parameters of the method and is also used to hold the values of the local variables. The parameters are stored first, beginning at index 0. If the frame is for a constructor or an instance method, the reference is stored at location 0. Then location 1 contains the first formal parameter, location 2 the second, and so on. For a static method, the first formal method parameter is stored in location 0, the second in location 1, and so on." https://core.ac.uk/download/pdf/61796001.pdf – rapt Mar 30 '19 at 05:53
-
While it is possible to reuse the variable index zero for other variables than `this` (which does not happen in practice with common compilers), it is a bit pointless to search for that, as the OP *wanted* `this`, when talking about “object which called invokevirtual”. I suppose, that’s also the reason why you came up with `wantedLocalVariableIndex = 0`. But what “name of the object” should this find, anyway. Seems that was an xy problem… – Holger May 02 '19 at 10:32
Here is how I solved this puzzle in my fork of the JavaFlow library. For the exact implementation please take a look at a CallSiteFinder.java in my Github repository.
The idea is the following. When you have method instruction, you may get the necessary stack size required for correct method invocation
Type.getArgumentsAndReturnSizes(methodInsnNode.desc) >> 2
Now move by instructions list starting from the given MethodInsnNode in the reverse direction and reducing the obtained stack size according to the OPCode of the every instruction encountered. Continue until your size is zero. At this point you have an instruction node that is used for "this" -- first argument for instance method call. It could be ALOAD (incl. this of the method you are visiting -- "ALOD 0"), AALOAD, GETSTATIC, GETFIELD or a result from the previous method call when several method calls are chained like
StringBuilder.append(...).append(..)

- 199
- 2
- 4