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

Peter Levart peter.levart at gmail.com
Sun Feb 7 22:57:02 UTC 2016



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/hadoop-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