1

I migrate my project to JDK 17. Everything works fine besides of one thing:

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

In my understanding the underline class implementing interface Path, can't be called due limited scope. How can I declare a reflective call using Path interface? Or there is another trick?

Exception:

java.lang.IllegalAccessException: 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 at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:392) at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:674) at java.base/java.lang.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) at org.aldan3.util.TemplateEngine.processResource(TemplateEngine.java:259) at org.aldan3.util.TemplateEngine.process(TemplateEngine.java:392) at 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) at org.aldan3.servlet.BasePageService.processView(BasePageService.java:381) at org.aldan3.servlet.BasePageService.serve(BasePageService.java:222) at 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) at rogatkin.web.WebAppServlet$WebAppContextFilter.doFilter(WebAppServlet.java:3219) at rogatkin.web.WebAppServlet$SimpleFilterChain.doFilter(WebAppServlet.java:3571) at rogatkin.web.WebAppServlet.service(WebAppServlet.java:1464) at Acme.Serve.Serve$ServeConnection.runServlet(Serve.java:2407) at Acme.Serve.Serve$ServeConnection.parseRequest(Serve.java:2326) at Acme.Serve.Serve$ServeConnection.run(Serve.java:2110) at Acme.Utils$ThreadPool$PooledThread.run(Utils.java:1238) at java.base/java.lang.Thread.run(Thread.java:833)

The exception source

Adding an object to a Map and then methods of it will be called using reflection

Since here are lot of misunderstandings of the question, I created a minimal testing example as Unmitigated pointed

The problem appeared so interesting, so my friend from Meta, asked if I can show any use case. Sure, I can. A use case

user2305886
  • 784
  • 8
  • 18

1 Answers1

2

You should contact the author of org.aldan3.util.TemplateEngine.

Apparently it is using reflection to try to access the internals of sun.nio.fs.UnixPath. It shouldn't do that. This kind of access to internals was always a really bad idea. In more recent Java releases they have been moving to prevent applications from doing this. (See JEP 403 for more details.)

I can't immediately see why this code is performing this illegal access. But there should be a way to implement the functionality (whatever it is) in a way that avoids the problem.

  • If you are the author, if you explain what that the code is doing and why, then maybe someone can suggest an alternative.

  • If you are not the author (and you don't have the time and / or skills to deep-dive the code, etcetera), you would do best to raise an "issue" on the Github site for the software. Then decide what to do ... depending on the author's response.


In my understanding the underline class implementing interface Path, can't be called due limited scope. How can I declare a reflective call using Path interface? Or there is another trick?

It may be possible to do this via the workaround described in the Java 17 release notes:

JEP 403: Strongly Encapsulate JDK Internals (JDK-8266851) core-libs

Strongly encapsulate all internal elements of the JDK, except for critical internal APIs such as sun.misc.Unsafe.

With this change, the java launcher option --illegal-access is obsolete. If used on the command line it causes a warning message to be issued, and otherwise has no effect. Existing code that must use internal classes, methods, or fields of the JDK can still be made to work by using the --add-opens launcher option, or the Add-Opens JAR-file manifest attribute, to open specific packages.

For further details, please see JEP 403.

However, my recommendation would be to change your code so that it doesn't need to break encapsulation and refer to JDK internals.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • There is no any mentioning of sun.nio.fs.UnixPath in any piece of a code of the project. It operates only with Path interface. Say more, an underline implementation will be different on Windows or MacOS. Sure, if I wrap Path in mine Path object, the code starts working. But, is this the goal of Oracle? I doubt. – user2305886 Oct 29 '21 at 01:52
  • @user2305886 - So here's the thing. I don't understand what that code is really doing and how exactly it is trying to access an internal field. It may well be doing it by accident (!) That is for you and / or the author of the code to figure out. The fact that you are not explicitly mentioning that class in this part of the code (or maybe anywhere in the codebase) doesn't mean that it isn't happening via some reflective pathways. – Stephen C Oct 29 '21 at 02:02
  • 1
    The goal of Oracle is to get rid of application dependencies on JDK internals that tend to cause applications to break when the Java version changes. The JEP explains this. But that is immaterial to solving your problem. – Stephen C Oct 29 '21 at 02:05
  • all your points are incredibly good, I created a minimal example, so please point me where any dependencies on Java internal implementation specified? – user2305886 Oct 29 '21 at 03:33
  • @StephenC Apparently, the eternal Java standard of "enumerate this object's properties" is now forbidden for unexported classes, even when the class implements exported interfaces, which is deranged. (I'm running into exactly this problem in an entirely different context, annotation processors, where I'm trying to invoke a method defined by `QualifiedNameable` but implemented by `Symbol`.) – chrylis -cautiouslyoptimistic- May 02 '23 at 21:05