1

我将我的项目迁移到 JDK 17。除了一件事之外,一切都很好:

class org.aldan3.util.TemplateEngine cannot access class sun.nio.fs.UnixPath (in module java.base) because module java.base does not export sun.nio.fs to unnamed module @c12d4d

据我了解,实现接口路径的下划线类,由于范围有限,不能称为。如何使用 Path 接口声明反射调用?或者还有什么技巧?

例外:

java.lang.IllegalAccessException:类 org.aldan3.util.TemplateEngine 无法访问类 sun.nio.fs.UnixPath(在模块 java.base 中),因为模块 java.base 不会将 sun.nio.fs 导出到未命名的模块 @c12d4d java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:674) 的 java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:674) 的 java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:392)。 reflect.Method.invoke(Method.java:560) at org.aldan3.util.TemplateEngine.processMethodCall(TemplateEngine.java:1731) at org.aldan3.util.TemplateEngine.process(TemplateEngine.java:1397) at org.aldan3 .util.TemplateEngine.process(TemplateEngine.java:852) 在 org.aldan3.util.TemplateEngine.processResource(TemplateEngine.java:259) 在 org.aldan3.util.TemplateEngine.process(TemplateEngine.java:392) 在 org. aldan3.util.TemplateEngine。processResource(TemplateEngine.java:259) at org.aldan3.util.TemplateEngine.process(TemplateEngine.java:432) at org.aldan3.util.TemplateEngine.processResource(TemplateEngine.java:259) at org.aldan3.util.TemplateEngine .process(TemplateEngine.java:280) 在 org.aldan3.servlet.BasePageService.processView(BasePageService.java:381) 在 org.aldan3.servlet.BasePageService.serve(BasePageService.java:222) 在 org.aldan3.servlet。 FrontController.doRequest(FrontController.java:244) at org.aldan3.servlet.FrontController.service(FrontController.java:159) at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) at rogatkin.web.WebAppServlet $SimpleFilterChain.doFilter(WebAppServlet.java:3599) 在 rogatkin.web.WebAppServlet$WebAppContextFilter.doFilter(WebAppServlet.java:3219) 在 rogatkin.web.WebAppServlet$SimpleFilterChain.doFilter(WebAppServlet.java:3571) 在 rogatkin.web.WebAppServlet.service(WebAppServlet.java:1464) 在 Acme.Serve.Serve$ServeConnection.runServlet(Serve.java:2407) 在 Acme.Serve.Serve$ServeConnection.parseRequest(Serve.java:2326 ) 在 Acme.Serve.Serve$ServeConnection.run(Serve.java:2110) 在 Acme.Utils$ThreadPool$PooledThread.run(Utils.java:1238) 在 java.base/java.lang.Thread.run(Thread.爪哇:833)

异常源

将对象添加到 Map 然后将使用反射调用它的方法

由于这里有很多对问题的误解,我创建了一个最小的测试示例,如 Unmitigated 指出的

这个问题看起来很有趣,所以我来自 Meta 的朋友问我是否可以展示任何用例。我当然可以。 一个用例

4

1 回答 1

3

你应该联系作者org.aldan3.util.TemplateEngine

显然它正在使用反射来尝试访问sun.nio.fs.UnixPath. 它不应该那样做。这种对内部的访问总是一个非常糟糕的主意。在最近的 Java 版本中,他们一直在移动以防止应用程序这样做。(有关详细信息,请参阅JEP 403。 )

我无法立即看出为什么这段代码会执行这种非法访问。但是应该有一种方法来实现功能(无论它是什么)以避免问题。

  • 如果您是作者,如果您解释了代码在做什么以及为什么,那么也许有人可以提出替代方案。

  • 如果您不是作者(并且您没有时间和/或技能来深入研究代码等),您最好在 Github 网站上为该软件提出一个“问题”。然后决定做什么......取决于作者的回应。


据我了解,实现接口路径的下划线类,由于范围有限,不能称为。如何使用 Path 接口声明反射调用?或者还有什么技巧?

可以通过Java 17 发行说明中描述的解决方法来做到这一点:

JEP 403:强烈封装 JDK 内部 (JDK-8266851) 核心库

强烈封装 JDK 的所有内部元素,除了关键的内部 API,例如sun.misc.Unsafe.

进行此更改后,java 启动器选项--illegal-access已过时。如果在命令行上使用,则会发出警告消息,否则无效。必须使用 JDK 的内部类、方法或字段的现有代码仍然可以通过使用--add-opens启动器选项或Add-OpensJAR 文件清单属性来打开特定包。

有关详细信息,请参阅JEP 403

但是,我的建议是更改您的代码,以便它不需要破坏封装并参考 JDK 内部。

于 2021-10-28T00:54:20.477 回答