使用Javassist获取方法参数的名称

时间:2013-12-01 20:37:30

标签: javassist

我有一个CtMethod实例,但我不知道如何从中获取参数名称(不是类型)。我试过了getParameterTypes,但它似乎只返回了类型。

我认为这是可能的,因为我使用的库没有源代码,只有类文件,我可以在IDE中看到方法参数的名称。

4 个答案:

答案 0 :(得分:8)

确实可以检索参数的名称,但仅当代码已使用调试符号编译时,否则您将无法执行此操作。

要检索此信息,您必须访问方法的本地变量表。有关此数据结构的详细信息,建议您查看4.7.13. The LocalVariableTable Attributejvm spec部分。正如我通常所说的那样,JVM规范可能看起来很笨重但是当你在这个级别工作时它是一个非常宝贵的朋友!

访问ctmethod的本地变量表属性

  CtMethod method = .....;
  MethodInfo methodInfo = method.getMethodInfo();
  LocalVariableAttribute table = methodInfo.getCodeAttribute().getAttribute(javassist.bytecode.LocalVariableAttribute.tag);

现在,您已在table变量中选择了本地变量属性。

检测localVariables的数量

   int numberOfLocalVariables = table.tableLenght(); 

现在请记住有关numberOfLocalVariables中数字的两件事:

  • 第一个:在方法正文中定义的局部变量也将计入tableLength();
  • 第二:如果您使用非静态方法,那么this变量。

本地变量表的顺序如下:

|this (if non static) | arg1 | arg2 | ... | argN | var1 | ... | varN|

重新获取参数名称

现在,如果您想要检索上一个示例中的arg2名称,那么它就是数组中的第3个位置。因此,您执行以下操作:

 // remember it's an array so it starts in 0, meaning if you want position 3 => use index 2
 int frameWithNameAtConstantPool = table.nameIndex(2); 
 String variableName = methodInfo.getConstPool().getUtf8Info(frameAtConstantPool)

现在,您的变量名称位于variableName

旁注:我带您浏览了风景路线,以便您可以了解更多有关Java(和javassists)内部的信息。但是已经有工具可以为你做这种操作,我至少可以记住一个名为paranamer的名字。您可能也想看看它。

希望它有所帮助!

答案 1 :(得分:3)

如果您实际上并不想要参数的名称,但只是希望能够访问它们,您可以使用" $ 1,$ 2,..."见in this tutorial

答案 2 :(得分:0)

如果您进行转换,它可以与Javaassist 3.18.2(以及以后的至少3.19)一起使用,如下所示:

LocalVariableAttribute nameTable = (LocalVariableAttribute)methodInfo.getCodeAttribute().getAttribute(LocalVariableAttribute.tag);

答案 3 :(得分:0)

Paranamer具有可用于检索参数名称的方法,即使该参数名称未使用调试符号进行编译也是如此。我已经用过了,对我来说效果很好。试试看。 paranamer link

jar link