PedroD
PedroD

Reputation: 6023

Using Java Reflection for getting all defined variables in runtime context (voodoo inside)

I have this code:

package teste;

public class Teste {

    public static void main(String[] args) {
        String arroz = "abc";
        Integer banana = 123;

        vaiBuscar();
    }

    private static void vaiBuscar() {
        Object[] obj = theMagicMethod();
        System.out.println(((String) obj[0])); 
        System.out.println(((Integer) obj[1])); 
    }
}

And the output should be:

abc
123

Now the funny part is that the only method I can define is theMagicMethod(). So I need to go fetch all variables values that are defined in upper methods that invoked me. If there's a way to do this, probably it is through reflection.

Summing it up: If you could not edit any part of the code besides defining the method theMagicMethod(), how should this method be so that the output of this program is the one I wrote above?

Thanks!

Edit: This doesn't really need reflection to be solved. Any way will fit, it just needs to work.

Upvotes: 2

Views: 529

Answers (3)

Stephan Rauh
Stephan Rauh

Reputation: 3160

Most likely it's a bad idea to use something like this in production code.

That said, I have to admit I've been looking for a way to inspect the variables on the stack trace, too :). It may be a stupid idea, but it's also an interesting one.

It can't be completely impossible. True, the byte code seems to be compiled in a way making it impossible, but every debugger manages to do it. But it's definitely impossible via reflection, and it's also impossible to access variables of the caller method without dirty hacks. If it was possible, you could escape the scope of the variables, and you'd ruin the garbage collector's day.

In any case, the variable names get lost (that's why the debugger of Eclipse often simply displays parameters as "arg1", "arg2" etc.).

You could try to write a java agent and use the instrumentation API. To get started, you may have a look at this article: http://blog.javabenchmark.org/2013/05/java-instrumentation-tutorial.html. Julien Poaletti didn't try to read variables, but I guess you could build on his example.

But again, using a custom agent is nothing a operations department should ever allow. Use at own risk!

Upvotes: 3

Edwin Buck
Edwin Buck

Reputation: 70909

Within the methods, the variable names are lost.

Java is a stack based machine, and so a method that looks like

public int add(int first, int second) {
  int sum = first + second;
  return sum;
}

is going to lose the naming of sum in bytecode that roughly reads as

  pushInt firstParameter
  pushInt secondParameter
  addInt
  returnInt

Note that the intermediate variable name sum is completely destroyed in the compiling process, so there is no means to retrieve it from the run time.

However, there are many other items which must be referred to by name, so their names are not destroyed at runtime. Some of these include

 names of classes
 names of members
 names of methods
 names of enums
 names of interfaces

So it is possible to get a subset of all the used names in a .java file; but, such a subset is not going to include the internal names of any block of code.

Now, if you compile with some debugging options set (like -g), you can improve upon the number of names accessible; however, there is no guarantee that any class you read in was compiled with debugging flags set (in fact, most classes are not compile with debugging flags set to improve loading performance).

If you can't do it for any class, you can't do it for a JVM.

Now, if you wanted to try your hand at getting all of the information that's not destroyed in the JVM, you could play around with JDWP (the debugging wire protocol) and take a peek at what is exposed; however, I would doubt it would be able to reach "everything", as it would only be able to read "everything loaded by the class loader" and (keeping in mind the above statements) only what survived compilation at that.

Upvotes: 3

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279880

This is impossible to do. Reflection doesn't let you look at the inner implementation of methods.

There is no way in Java to look at the stack and extract variables or any values declared in stacked method stack frames.

Upvotes: 1

Related Questions