1

我正在使用 java 模块系统测试一些字节码生成库。我已经编译了 java 11,并对 java.base module-info.java 进行了以下更改:

module java.base {
  ...
  exports java.lang.reflect to <some java and custom modules>;
  ...
}

然后我用“--illegal-access=deny”选项启动java。当我将此编译后的 java 版本与 javassist 库一起使用时,它会在未命名的模块中生成以下类:

public class SomeJavassistProxy extends SomeClass implements WriteReplaceInterface, ProxyObject {
   private MethodHandler handler;
   private static Method[] _methods_;
   ...

Java 抛出某种“java.lang.IllegalAccessError class SomeJavassistProxy(in unnamed module) cannot access class java.lang.reflect.Method(in module java.base) because module java.base does not export java.lang.reflect to unnamed模块”。

这是预期的行为。

然后我尝试了 bytebuddy 库,它生成了以下类:

public class SomeClass$HibernateProxy$7DKVefUe extends SomeClass implements HibernateProxy, ProxyConfiguration {
   private Interceptor $$_hibernate_interceptor;
   // $FF: synthetic field
   private static final Method cachedValue$ghVgnbHc$4cscpe1 = Object.class.getMethod("toString");
   // $FF: synthetic field
   private static final Method cachedValue$ghVgnbHc$o23rrk2 = HibernateProxy.class.getMethod("getHibernateLazyInitializer");
   ...

这个类也在未命名的模块中生成。但这一次它可以工作并且不会引发任何错误。不知何故,它可以访问 java.lang.reflect,尽管该包不应该被未命名的模块访问。

我看到的唯一区别是 bytebuddy 生成的类中带有 java.lang.reflect.Method 的合成字段。

所以,我的问题是,java 模块系统是否不适用于合成字段?

4

1 回答 1

1

对不起这是我的错。
事实证明,只有当您在无法访问该包的模块(在我的情况下为未命名模块)中实际调用安全包(在我的情况下为 java.lang.reflect)中的方法时,才会引发 IllegalAccessError。
如果只是对安全包的引用,则不会引发异常。

在带有 bytebuddy 的示例中,只有对未命名模块中的 Method 类的引用。这个引用被传递给 Interceptor 类(在我的例子中,它属于可以访问 java.lang.reflect 的自动模块),其中发生了 Method 的实际调用。

因此,它与合成字段无关。

于 2021-10-10T20:42:52.680 回答