Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: list fields used in a method

In Java, how can I get the Fields that are used in a method ?

Basically, this is the same questions as this one in .NET. I dont wan't to list the fields from a Class, but to list the fields that are used in a given method of the class.

Example:

public class A {
 int a;
 int b;

public int bob(){
 return a-b;
}

I want to get the fields like this:

Fields[] fields = FieldReader.(A.class.getMethod("bob"));

So that fields[0]=A.a and fields[1]=A.b

I didn't find any solution using standard Reflection. Do you think bytecode manipulation library such as ASM are a way to go ?

like image 793
Julien Avatar asked Oct 19 '22 12:10

Julien


1 Answers

Here is an example with javassist (you need to add it as a dependency, depending on your dependency manager preferences).

This code list the field being accessed in the public void doSomething(); method.

package bcm;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import javassist.bytecode.InstructionPrinter;

public class Person {

    String name;
    String surname;
    int age;

    boolean candrink = false;

    public Person(String name, String surname, int age) {
        super();
        this.name = name;
        this.surname = surname;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSurname() {
        return surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void doSomething() {
        if (this.age > 18) {
            candrink = true;
        }
    }

    public static void main(String[] args) throws IOException,
            CannotCompileException {
        ClassPool pool = ClassPool.getDefault();
        try {
            CtClass cc = pool.get("bcm.Person");
            CtMethod m = cc.getDeclaredMethod("doSomething", null);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PrintStream ps = new PrintStream(baos);
            InstructionPrinter i = new InstructionPrinter(ps);
            i.print(m);
            String content = baos.toString();

            for (String line : content.split("\\r?\\n")) {
                if (line.contains("getfield")) {
                    System.out.println(line.replaceAll("getfield ", ""));
                }
            }

        } catch (NotFoundException e) {
            e.printStackTrace();
        }
    }

}

HTH

like image 111
Fafhrd Avatar answered Nov 02 '22 06:11

Fafhrd