cannot access class jdk.internal.ref.Cleaner (in module java.base) because module java.base does not export jdk.internal.ref to unnamed module
uschindler at apache.org
Sat Aug 6 17:59:59 UTC 2016
if you are interested, the Apache Lucene team has a implementation of the unmapper that's safe with any currently known Java version. The problem with using pure reflection is that you cannot be sure before actually calling the unmappinmg that it works. We use MethodHandles to work around that (early linking before actually calling). It uses Alan's Runnable trick.
We had this problem in Lucene 5 versions, which are broken (until 5.5.1) with recent Java 9, because we used reflection and we were not able to detect in a 100% safe way that the unmapping APIs are accessible and actually work. We changed the code in Lucene 6+ to use MethodHandles for early linking before trying to call anything, so there is no reflection involved at unmapping time (only an invokeExact).
This code does the lookup and inspection + building the MethodHandle (wrapped in AccessController):
The result is Lucene specific implementation of BufferCleaner (an interface), but it basically only calls a MethodHandle that unmaps the ByteBuffer. The MethodHandle also contains all NULL checks needed and can be safely called. The MethodHandle is here:
and invoked like that:
I hope that helps! Apache Lucene, Apaceh Solr, and Elasticsearch are using this in production since beginning of this year.
uschindler at apache.org
ASF Member, Apache Lucene PMC / Committer
> -----Original Message-----
> From: jigsaw-dev [mailto:jigsaw-dev-bounces at openjdk.java.net] On Behalf
> Of Julien Gouesse
> Sent: Saturday, August 6, 2016 5:45 PM
> To: Julien Gouesse <gouessej at yahoo.fr>; Alan Bateman
> <Alan.Bateman at oracle.com>; jigsaw-dev at openjdk.java.net
> Subject: Re: cannot access class jdk.internal.ref.Cleaner (in module java.base)
> because module java.base does not export jdk.internal.ref to unnamed
> You're right, jdk.internal.ref.Cleaner implements Runnable unlike
> It works, I no longer need "--add-exports". Thank you very much.
> Le Samedi 6 août 2016 17h19, Julien Gouesse <gouessej at yahoo.fr> a écrit :
> It doesn't work:
> [gouessej at localhost test-classes]$ ~/Téléchargements/jdk-9/bin/java -cp
> ../classes:../test-classes --add-exports java.base/jdk.internal.ref=ALL-
> UNNAMED engine/misc/TestDeallocationHelper
> Unrecognized option: --add-exports
> Error: Could not create the Java Virtual Machine.
> Error: A fatal exception has occurred. Program will exit.
> Ok I'm going to try to treat it as a Runnable.
> Le Samedi 6 août 2016 16h02, Alan Bateman <Alan.Bateman at oracle.com> a
> écrit :
> On 06/08/2016 02:52, Julien Gouesse wrote:
> > Hi
> > I need to run the cleaner of a direct NIO byte buffer by using the reflection
> API to access to non public APIs as I successfully did with previous versions of
> Java. The cleaner is in the class "Cleaner" in the package "jdk.internal.ref" in
> the module "java.base" and my own module is unnamed. Then, I tried to
> pass "--add-exports java.base/jdk.internal.ref=ALL-UNNAMED" to the
> command "java" but I get the following exception:
> > [gouessej at localhost test-classes]$ ~/Téléchargements/jdk-9/bin/java -cp
> ../classes:../test-classes engine/misc/TestDeallocationHelper --add-exports
> You've put the --add-exports option after your main class on the command
> line, try place it before the main class so that it's considered as an
> argument to the java launcher rather an argument to your main class.
> One other thing to point out if that jdk.internal.ref.Cleaner is a
> Runnable so you can at least stay in the world of standard types.
More information about the jigsaw-dev