1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 import java.security.AccessController;
25 import java.security.PrivilegedAction;
26
27
28
29
30 final class CleanerJava9 implements Cleaner {
31 private static final InternalLogger logger = InternalLoggerFactory.getInstance(CleanerJava9.class);
32
33 private static final Method INVOKE_CLEANER;
34
35 static {
36 final Method method;
37 final Throwable error;
38 if (PlatformDependent0.hasUnsafe()) {
39 final ByteBuffer buffer = ByteBuffer.allocateDirect(1);
40 Object maybeInvokeMethod = AccessController.doPrivileged(new PrivilegedAction<Object>() {
41 @Override
42 public Object run() {
43 try {
44
45 Method m = PlatformDependent0.UNSAFE.getClass().getDeclaredMethod(
46 "invokeCleaner", ByteBuffer.class);
47 m.invoke(PlatformDependent0.UNSAFE, buffer);
48 return m;
49 } catch (NoSuchMethodException e) {
50 return e;
51 } catch (InvocationTargetException e) {
52 return e;
53 } catch (IllegalAccessException e) {
54 return e;
55 }
56 }
57 });
58
59 if (maybeInvokeMethod instanceof Throwable) {
60 method = null;
61 error = (Throwable) maybeInvokeMethod;
62 } else {
63 method = (Method) maybeInvokeMethod;
64 error = null;
65 }
66 } else {
67 method = null;
68 error = new UnsupportedOperationException("sun.misc.Unsafe unavailable");
69 }
70 if (error == null) {
71 logger.debug("java.nio.ByteBuffer.cleaner(): available");
72 } else {
73 logger.debug("java.nio.ByteBuffer.cleaner(): unavailable", error);
74 }
75 INVOKE_CLEANER = method;
76 }
77
78 static boolean isSupported() {
79 return INVOKE_CLEANER != null;
80 }
81
82 @Override
83 public void freeDirectBuffer(ByteBuffer buffer) {
84
85
86 if (System.getSecurityManager() == null) {
87 try {
88 INVOKE_CLEANER.invoke(PlatformDependent0.UNSAFE, buffer);
89 } catch (Throwable cause) {
90 PlatformDependent0.throwException(cause);
91 }
92 } else {
93 freeDirectBufferPrivileged(buffer);
94 }
95 }
96
97 private static void freeDirectBufferPrivileged(final ByteBuffer buffer) {
98 Exception error = AccessController.doPrivileged(new PrivilegedAction<Exception>() {
99 @Override
100 public Exception run() {
101 try {
102 INVOKE_CLEANER.invoke(PlatformDependent0.UNSAFE, buffer);
103 } catch (InvocationTargetException e) {
104 return e;
105 } catch (IllegalAccessException e) {
106 return e;
107 }
108 return null;
109 }
110 });
111 if (error != null) {
112 PlatformDependent0.throwException(error);
113 }
114 }
115 }