Javassist似乎生成了无效的字段访问代码

时间:2017-08-24 13:38:25

标签: java javassist bytecode-manipulation

我正在尝试在启动应用程序期间使用其他功能扩充一些代码。整个设置本身工作正常,但有一点我认为javassist可能会生成错误的代码。

我是在特定类的特定方法上执行此操作,之前检查过返回值实际上是StringBuilderStringBuffer类型。

ctMethod.insertAfter("$_.SOME_METHOD(); $_.SOME_FIELD = <...>;");

SOME_METHOD()和SOME_FIELD都在AbstractStringBuilder中声明,StringBuilderStringBuffer的超类。两者都被定义为公共的,java.lang.AbstractStringBuilder本身只是包私有。

操作本身是成功的,但执行此代码会导致错误&#34; java.lang.IllegalAccessError: tried to access class java.lang.AbstractStringBuilder from class <...>&#34;。通过打印调试我发现,访问该方法工作正常,但访问该字段崩溃。

所以我检查了生成的字节码:

...
invokevirtual #41 <java/lang/StringBuilder.SOME_METHOD>
...
getfield #72 <java/lang/AbstractStringBuilder.SOME_FIELD>
...

因此,为了访问该方法,它解析为StringBuilder本身,但是对于该字段,它解析为AbstractStringBuilder,这显然不能从修改后的代码的位置访问。顺便说一句,反编译的字节码看起来很好。

我也在我的静态代码中访问这个字段,所以我检查了这个字节码:

...
getfield #37 <java/lang/StringBuilder.SOME_FIELD>
...

这是默认编译器编译的代码,它不使用AbstractStringBuilder作为参考。

所以我的问题是:我是否监督了有关JVMs可见性和继承概念的内容,还是javassist没有正确解决这个问题? 我希望,我的解释是可以理解的 - 否则让我知道,我会尽力加强它。

1 个答案:

答案 0 :(得分:1)

这是Javassist中的一个错误。

字段不是虚拟的,通过命名另一个类,您实际上可以访问需要可供相关类访问的不同(阴影)字段。