Java: 列出方法中使用的字段
Java: list fields used in a method
在 Java 中,如何获取方法中使用的字段?
基本上,这是与 this one in .NET 相同的问题。我不想列出 Class 中的字段,而是列出 class.
的给定方法中使用的字段
示例:
public class A {
int a;
int b;
public int bob(){
return a-b;
}
我想得到这样的字段:
Fields[] fields = FieldReader.(A.class.getMethod("bob"));
所以 fields[0]=A.a
和 fields[1]=A.b
我没有找到任何使用标准反射的解决方案。你认为像 ASM 这样的字节码操作库是可行的方法吗?
这是一个 javassist 的示例(您需要将其添加为依赖项,具体取决于您的依赖项管理器首选项)。
此代码列出了在 public void doSomething();
方法中访问的字段。
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
一旦你加载了一个类节点,这就变得非常容易了。
// Assuming you have loaded classNode
for (MethodNode method : classNode.methods){
for (AbstractInsnNode ain : method.instructions.toArray()) {
if (ain.getType() == AbstractInsnNode.FIELD_INSN) {
FieldInsnNode fin = (FieldInsnNode) ain;
//fin.name = Field name
//fin.owner = ClassNode's name
}
}
}
加上 ASM 比 Javassist 等库快得多。
在 Java 中,如何获取方法中使用的字段?
基本上,这是与 this one in .NET 相同的问题。我不想列出 Class 中的字段,而是列出 class.
的给定方法中使用的字段示例:
public class A {
int a;
int b;
public int bob(){
return a-b;
}
我想得到这样的字段:
Fields[] fields = FieldReader.(A.class.getMethod("bob"));
所以 fields[0]=A.a
和 fields[1]=A.b
我没有找到任何使用标准反射的解决方案。你认为像 ASM 这样的字节码操作库是可行的方法吗?
这是一个 javassist 的示例(您需要将其添加为依赖项,具体取决于您的依赖项管理器首选项)。
此代码列出了在 public void doSomething();
方法中访问的字段。
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
一旦你加载了一个类节点,这就变得非常容易了。
// Assuming you have loaded classNode
for (MethodNode method : classNode.methods){
for (AbstractInsnNode ain : method.instructions.toArray()) {
if (ain.getType() == AbstractInsnNode.FIELD_INSN) {
FieldInsnNode fin = (FieldInsnNode) ain;
//fin.name = Field name
//fin.owner = ClassNode's name
}
}
}
加上 ASM 比 Javassist 等库快得多。