We don't need jdk.internal.ref.Cleaner any more

Uwe Schindler uschindler at apache.org
Sun Feb 7 23:25:21 UTC 2016


Hi Peter,

as discussed before in the other thread about move to jdk.internal: this looks fine to Apache Lucene. We have a separate issue to fix this for Java 9: https://issues.apache.org/jira/browse/LUCENE-6989

Currently the patch on the Lucene issue tries to cast the jdk.internal.Cleaner to Runnable; but with your patch, one would just need to cast to java.lang.ref.Cleaner$Cleanable (which is public anyways) and call clean().

The Runnable workaround was done for Lucene, Hadoop, and Netty, but with your current patch this extra hack will be obsolete:
http://cr.openjdk.java.net/~chegar/8148117/src/java.base/share/classes/jdk/internal/ref/Cleaner.java.udiff.html

So, I am fine with both solutions as workaround, if we can enforce unmapping - until an official and "safe" solution is found.

I was discussing with Andrew Haley and Mark Reinhold on FOSDEM about an "official way" to unmap ByteBuffers and there seems to be a really cool idea to make MappedByteBuffer/DirectByteBuffer implement Closeable, so unmapping may work without the horrible performance degradion on every access by using some extra safepoint and changed volatile semantics using a annotation in Hotspot.

Uwe

-----
Uwe Schindler
uschindler at apache.org 
ASF Member, Apache Lucene PMC / Committer
Bremen, Germany
http://lucene.apache.org/
> -----Original Message-----
> From: core-libs-dev [mailto:core-libs-dev-bounces at openjdk.java.net] On
> Behalf Of Peter Levart
> Sent: Sunday, February 07, 2016 11:57 PM
> To: Jeremy Manson <jeremymanson at google.com>
> Cc: Core-Libs-Dev <core-libs-dev at openjdk.java.net>
> Subject: Re: We don't need jdk.internal.ref.Cleaner any more
> 
> 
> 
> On 02/07/2016 11:20 PM, Peter Levart wrote:
> >
> >
> > On 02/07/2016 08:01 PM, Jeremy Manson wrote:
> >> Hadoop seems to use sun.misc.Cleaner:
> >>
> >>
> http://grepcode.com/file/repo1.maven.org/maven2/org.apache.hadoop/ha
> doop-common/2.7.1/org/apache/hadoop/crypto/CryptoStreamUtils.java
> >>
> >> So you may want to keep it around transitionally (a la Unsafe).
> >
> > JEP 260 [1] was listing sun.misc.Cleaner as a critical API, but
> > recently, it was decided to "hide" it away into jdk.internal.ref
> > package which will not be exported [2]. The reasoning was this:
> >
> > "sun.misc.Cleaner ( was previously listed as a critical internal API,
> > but on further investigation has been moved to an open issue, for the
> > following reasons: 1) its primary use in the JDK is within NIO direct
> > buffers to release native memory. The base module cannot have a
> > dependency on jdk.unsupported so will need to be updated to use an
> > alternative cleaner, 2) the usage of Cleaner outside the JDK, as
> > determined by corpus analysis, has largely been observed to hack into
> > private fields of the internal NIO direct buffer classes to explicitly
> > release native memory. As stated in 1), the type of the cleaner used
> > by NIO direct buffers will have to change. Given this, and the fact
> > that JDK 9 has a new general purposed cleaner API,
> > java.lang.ref.Cleaner, the value of keep sun.misc.Cleaner is
> > questionable."
> >
> > If the decision to remove sun.misc.Cleaner was partly influenced by
> > the desire to maintain just 2 instead of 3 Cleaner(s), then my
> > proposal to migrate JDK code to the public API might enable Oracle to
> > reconsider keeping sun.misc.Cleaner.
> 
> OTOH, what hadoop is doing is exactly the usage described in the above
> reasoning for removing sun.misc.Cleaner.
> 
> Hadoop use case:
> 
>      public static void freeDB(ByteBuffer buffer) {
>          if (buffer instanceof sun.nio.ch.DirectBuffer) {
>              final sun.misc.Cleaner bufferCleaner =
>                  ((sun.nio.ch.DirectBuffer) buffer).cleaner();
>              bufferCleaner.clean();
>          }
>      }
> 
> can be rewritten using reflection to be compatible with either
> sun.misc.Cleaner (on JDK 8 or less) or java.lang.ref.Cleaner$Cleanable
> (on JDK 9 or more):
> 
>      static final Method cleanMethod;
> 
>      static {
>          try {
>              Class<?> cleanerOrCleanable;
>              try {
>                  cleanerOrCleanable = Class.forName("sun.misc.Cleaner");
>              } catch (ClassNotFoundException e1) {
>                  try {
>                      cleanerOrCleanable =
> Class.forName("java.lang.ref.Cleaner$Cleanable");
>                  } catch (ClassNotFoundException e2) {
>                      e2.addSuppressed(e1);
>                      throw e2;
>                  }
>              }
>              cleanMethod = cleanerOrCleanable.getDeclaredMethod("clean");
>          } catch (Exception e) {
>              throw new Error(e);
>          }
>      }
> 
>      public static void freeDB_JDK8or9(ByteBuffer buffer) {
>          if (buffer instanceof sun.nio.ch.DirectBuffer) {
>              final Object bufferCleaner =
>                  ((sun.nio.ch.DirectBuffer) buffer).cleaner();
> 
>              try {
>                  if (bufferCleaner != null) {
>                      cleanMethod.invoke(bufferCleaner);
>                  }
>              } catch (InvocationTargetException | IllegalAccessException
> e) {
>                  throw new Error(e);
>              }
>          }
>      }
> 
> 
> I thought about this use case and even kept the name of the method on
> sun.nio.ch.DirectBuffer::cleaner to make things easier although the
> return type in my patched DirectBufer is called
> java.lang.ref.Cleaner$Cleanable.
> 
> 
> Regards, Peter
> 
> >
> > [1] https://bugs.openjdk.java.net/browse/JDK-8132928
> > [2] https://bugs.openjdk.java.net/browse/JDK-8148117
> >
> > Regards, Peter
> >
> >>
> >> Jeremy
> >>
> >> On Sun, Feb 7, 2016 at 2:53 AM, Peter Levart <peter.levart at gmail.com
> >> <mailto:peter.levart at gmail.com>> wrote:
> >>
> >>     Hi,
> >>
> >>     sun.misc.Cleaner has been moved to internal package
> >>     jdk.internal.ref recently [1] to clean-up sun.misc namespace. But
> >>     now that:
> >>
> >>     - we have comparable public API (java.lang.ref.Cleaner &
> >>     Cleanable) [2]
> >>     - we have an internal shared java.lang.ref.Cleaner instance
> >>     (jdk.internal.ref.CleanerFactory.cleaner())
> >>     - sun.misc.Cleaner is not a special kind of Reference any more in
> >>     the JVM [3]
> >>
> >>     ...I think there's no reason to keep this special internal API
> >>     any more. It can be replaced with public API.
> >>
> >>     I propose to remove jdk.internal.ref.Cleaner class and replace
> >>     its usages with java.lang.ref.Cleaner and friends [4].
> >>
> >>     What do you say?
> >>
> >>     Regards, Peter
> >>
> >>
> >>     [1] https://bugs.openjdk.java.net/browse/JDK-8148117
> >>     [2] https://bugs.openjdk.java.net/browse/JDK-8138696
> >>     [3] https://bugs.openjdk.java.net/browse/JDK-8143847
> >>     [4]
> >>     http://cr.openjdk.java.net/~plevart/jdk9-
> dev/removeInternalCleaner/webrev.01/
> >>     <http://cr.openjdk.java.net/%7Eplevart/jdk9-
> dev/removeInternalCleaner/webrev.01/>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >




More information about the core-libs-dev mailing list