Question

Is there any way via Reflection or some other tool to introspect the fields within a method in Java?

So, for example:

public void someMethod() {
  int one = 1;
  int two = 2;
}

And introspecting to find the fields "one" and "two" of type int within the method "someMethod"? To my knowledge it's not possible in Reflection, but I'm hoping ASM or some other bytecode instrospecting tool is capable.

Was it helpful?

Solution

Fields differ from method local variables in different ways:

  • First of all, variables inside methods will not have names when represented in byte code.
  • Second, the compiler is allowed to optimize away such variables. There is no contract saying that these method local variables must be kept by the compiler. At the same time, the compiler can add as many local variables at it wants.

And there is another catch: in byte code, local variables are not specified with an explicit declaration in a similar way they are declared in Java source code. Instead, method local variables are only visible as a part of a method specific array of variables that contains all of the following variables in this order:

  • A reference to the object on which the method is called on (as long as the method is not static, then this reference is not included), this is the this reference.
  • A reference to all arguments of this method in the order as they are defined in the source code.
  • A reference to all local variables that are created in the method:

An method like m in this example:

class A {
  void m(Object arg) {
    Object o = "test";
  }
}

would therefore appear in the byte code as the following local variable array:

[Object (this), Object (arg), Object (o)]

With this knowledge, you can for example parse a class's method by using ASM and its MethodVisitor. Doing so, you could deduct:

  1. The local variable array has a size of three, hypothetically, you could have three local variables
  2. You would find out that the method is not static, therefore you can cross out the first variable and you are left with the possibility of two local variables.
  3. The method has one argument which is of type reference, you can therefore cross out another variable which leaves you with probably one local variable declaration.

Now you have to parse the method's byte code and you could find out that there is a reference of type String pushed into the third array spot. This would leave you with the finding that you declared some local variable of type String or one of its super types such as Object.

However, you can still not be sure if this local variable was added synthetically. for the reasons named above. There is not more to find out for you. (Watch out for long or double variables which take variable spots of the size of 2.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top