英文:
module jdk.proxy2 does not export com.sun.proxy.jdk.proxy2 to module ca.example.MyStore
问题
我正在尝试使用模块进行实验,并尝试使用反射在代理上调用方法。我收到以下错误:
java.lang.IllegalAccessException: 类 ca.example.MyStore.ProxyExample(位于模块 ca.exampe.MyStore 中)无法访问类 com.sun.proxy.jdk.proxy2.$Proxy10(位于模块 jdk.proxy2 中),因为模块 jdk.proxy2 未将 com.sun.proxy.jdk.proxy2 导出到模块 ca.example.MyStore
当尝试调用默认方法时,这是在代理实例上调用的方法调用,导致上述异常:
```java
public Object executeDefaultMethod() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
// 在应用程序模块化时不能使用代理,除非指定模块是开放的
// 开放模块说明:https://stackoverflow.com/questions/53927375/how-do-java-module-directives-impact-reflection-access-into-a-module
Object proxy = Proxy.newProxyInstance(getSystemClassLoader(), new Class<?>[] { Coupon.class },
(prox, method, args) -> {
if (method.isDefault()) {
// invokeDefault 是 Java 16 中的新功能
return InvocationHandler.invokeDefault(prox, method, args);
}
return null;
}
);
Method method = proxy.getClass().getMethod("itemDiscount");
return method.invoke(proxy);
}
有趣的是,如果我将模块设置为 open
,代码就可以正常工作。为什么会这样?这个错误告诉我什么?
<details>
<summary>英文:</summary>
I'm playing around with modules and am trying to use reflection to invoke a method on a proxy. I get the following error:
java.lang.IllegalAccessException: class ca.example.MyStore.ProxyExample (in module ca.exampe.MyStore) cannot access class com.sun.proxy.jdk.proxy2.$Proxy10 (in module jdk.proxy2) because module jdk.proxy2 does not export com.sun.proxy.jdk.proxy2 to module ca.example.MyStore
Here is the method invocation on the proxy instance that causes the above exception when the default method is attempted to be invoked:
public Object executeDefaultMethod() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
// can not use Proxy when the app is modularized unless you specify that the module is open
// open module notes: https://stackoverflow.com/questions/53927375/how-do-java-module-directives-impact-reflection-access-into-a-module
Object proxy = Proxy.newProxyInstance(getSystemClassLoader(), new Class<?>[] { Coupon.class },
(prox, method, args) -> {
if (method.isDefault()) {
// invokeDefault is new with Java 16
return InvocationHandler.invokeDefault(prox, method, args);
}
return null;
}
);
Method method = proxy.getClass().getMethod("itemDiscount");
return method.invoke(proxy);
}
Interestingly, if I `open` the module, the code works. Why is this? The reflective call is happening within code that exists in the module. What is this error telling me?
</details>
# 答案1
**得分**: 0
问题中示例失败的原因是由于JDK 16中的更改,使得JDK内部的强封装成为默认设置,如https://openjdk.org/jeps/396所述。
JDK 9引入了模块系统,并为了帮助迁移,弱封装成为默认设置。
从JDK 16开始,强封装成为默认设置。请参阅JEP中与问题示例相关的详细信息:
在Java 9中,我们通过利用模块来限制对其内部元素的访问,从而改进了JDK的安全性和可维护性。模块提供了强封装,这意味着
模块外的代码只能访问由该模块导出的包的公共和受保护的元素
这就是在`module-info.java`文件中导出`Coupon`类所以示例能够工作的原因:
导出ca.MyStore.domain.coupons
或者,可以将模块本身定义为`open`模块。这也可以工作,但可能不建议使用。
<details>
<summary>英文:</summary>
The reason the example in the question fails is due to changes in JDK 16 that make strong encapsulation of JDK internals the default setting as described in https://openjdk.org/jeps/396.
JDK 9 introduced the module system and to aid in migration, weak encapsulation was the default setting.
Starting with JDK 16, strong encapsulation is the default setting. See the relevant detail in the JEP here as it relates to the example in the question:
In Java 9, we improved both the security and the maintainability of the JDK by leveraging modules to limit access to its internal elements. Modules provide strong encapsulation, which means that
Code outside of a module can only access the public and protected elements of the packages exported by that module
This is why exporting the package the `Coupon` class in the `module-info.java` file allows the above example to work:
exports ca.MyStore.domain.coupons
Alternatively, one can define the module itself as an `open` module. This works, but is probably not recommended.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论