View Javadoc
1   /*
2   * Copyright 2017 The Netty Project
3   *
4   * The Netty Project licenses this file to you under the Apache License,
5   * version 2.0 (the "License"); you may not use this file except in compliance
6   * with the License. You may obtain a copy of the License at:
7   *
8   *   http://www.apache.org/licenses/LICENSE-2.0
9   *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations
14  * under the License.
15  */
16  package io.netty.util.internal;
17  
18  import io.netty.util.internal.logging.InternalLogger;
19  import io.netty.util.internal.logging.InternalLoggerFactory;
20  
21  import java.lang.reflect.InvocationTargetException;
22  import java.lang.reflect.Method;
23  import java.nio.ByteBuffer;
24  
25  /**
26   * Provide a way to clean a ByteBuffer on Java9+.
27   */
28  final class CleanerJava9 implements Cleaner {
29      private static final InternalLogger logger = InternalLoggerFactory.getInstance(CleanerJava9.class);
30  
31      private static final Method INVOKE_CLEANER;
32  
33      static {
34          final Method method;
35          final Throwable error;
36          if (PlatformDependent0.hasUnsafe()) {
37              ByteBuffer buffer = ByteBuffer.allocateDirect(1);
38              Object maybeInvokeMethod;
39              try {
40                  // See https://bugs.openjdk.java.net/browse/JDK-8171377
41                  Method m = PlatformDependent0.UNSAFE.getClass().getDeclaredMethod("invokeCleaner", ByteBuffer.class);
42                  m.invoke(PlatformDependent0.UNSAFE, buffer);
43                  maybeInvokeMethod = m;
44              } catch (NoSuchMethodException e) {
45                  maybeInvokeMethod = e;
46              } catch (InvocationTargetException e) {
47                  maybeInvokeMethod = e;
48              } catch (IllegalAccessException e) {
49                  maybeInvokeMethod = e;
50              }
51              if (maybeInvokeMethod instanceof Throwable) {
52                  method = null;
53                  error = (Throwable) maybeInvokeMethod;
54              } else {
55                  method = (Method) maybeInvokeMethod;
56                  error = null;
57              }
58          } else {
59              method = null;
60              error = new UnsupportedOperationException("sun.misc.Unsafe unavailable");
61          }
62          if (error == null) {
63              logger.debug("java.nio.ByteBuffer.cleaner(): available");
64          } else {
65              logger.debug("java.nio.ByteBuffer.cleaner(): unavailable", error);
66          }
67          INVOKE_CLEANER = method;
68      }
69  
70      static boolean isSupported() {
71          return INVOKE_CLEANER != null;
72      }
73  
74      @Override
75      public void freeDirectBuffer(ByteBuffer buffer) {
76          try {
77              INVOKE_CLEANER.invoke(PlatformDependent0.UNSAFE, buffer);
78          } catch (Throwable cause) {
79              PlatformDependent0.throwException(cause);
80          }
81      }
82  }