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

Javassist seems to generate invalid field access code

我正在尝试在我的应用程序启动期间使用附加功能来扩充一些代码。整个设置本身运行良好,但有一点我认为 javassist 可能会生成错误代码。

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

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

SOME_METHOD() 和SOME_FIELD 都在AbstractStringBuilder 中声明,StringBuilderStringBuffer 的superclass。两者都定义为 public,java.lang.AbstractStringBuilder 本身只是 package-private.

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

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

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

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

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

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

这是编译器默认编译的代码,没有引用AbstractStringBuilder。

所以我的问题是:我是否监督了有关 JVM 可见性和继承概念的某些事情,或者 javassist 没有正确解决这个问题? 我希望,我的解释是可以理解的 - 否则请告诉我,我会尽力改进它。

这是 Javassist 中的一个错误。

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