内省方法中的字段

时间:2013-12-05 01:38:09

标签: java api reflection bytecode

有没有办法通过Reflection或其他工具来反省 中的方法?

所以,例如:

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

并且反省在方法“someMethod”中找到int类型的字段“one”和“two”?据我所知,它在反射中是不可能的,但我希望ASM或其他一些字节码的内部检测工具能够实现。

1 个答案:

答案 0 :(得分:0)

字段与方法局部变量的区别在于:

  • 首先,当以字节代码表示时,方法内的变量将没有名称。
  • 其次,允许编译器优化这些变量。没有合同说这些方法局部变量必须由编译器保存。同时,编译器可以根据需要添加任意数量的局部变量。

还有另一个问题:在字节代码中,局部变量没有使用与Java源代码中声明的类似方式的显式声明来指定。相反,方法局部变量仅作为特定于方法的变量数组的一部分可见,该变量包含以下顺序的所有以下变量:

  • 对调用该方法的对象的引用(只要该方法不是static,则不包括此引用),这是this引用。
  • 按照源代码中定义的顺序引用此方法的所有参数。
  • 对方法中创建的所有局部变量的引用:

此示例中的m方法:

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

将在字节代码中显示为以下局部变量数组:

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

有了这些知识,您可以使用ASM及其MethodVisitor来解析类的方法。这样做,你可以扣除:

  1. 局部变量数组的大小为3,假设您可以有三个局部变量
  2. 您会发现该方法不是static,因此您可以删除第一个变量,并留下两个局部变量的可能性。
  3. 该方法有一个类型为 reference 的参数,因此您可以删除另一个变量,该变量可能会留下一个局部变量声明。
  4. 现在你必须解析方法的字节代码,你会发现有一个类型为String的引用被推入第三个数组点。这将使您发现您声明了一些类型为String的局部变量或其中一个超类型(如Object)。

    但是,您仍然无法确定此局部变量是否已合成 。由于上述原因。没有更多的东西可以找到你。 (注意longdouble变量,这些变量的大小为2的变量点。)