1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.util.internal;
17
18 import io.netty5.util.internal.logging.InternalLogger;
19 import io.netty5.util.internal.logging.InternalLoggerFactory;
20
21 import java.lang.invoke.MethodHandle;
22 import java.lang.invoke.MethodHandles;
23 import java.lang.invoke.MethodType;
24 import java.nio.ByteBuffer;
25 import java.security.AccessController;
26 import java.security.PrivilegedAction;
27
28
29
30
31 final class CleanerJava9 implements Cleaner {
32 private static final InternalLogger logger = InternalLoggerFactory.getInstance(CleanerJava9.class);
33
34 private static final MethodHandle INVOKE_CLEANER_HANDLE;
35
36 static {
37 final MethodHandle invokeCleanerHandle;
38 final Throwable error;
39 if (PlatformDependent0.hasUnsafe()) {
40 final ByteBuffer buffer = ByteBuffer.allocateDirect(1);
41 Object maybeInvokeMethodHandle = AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
42 try {
43 MethodHandles.Lookup lookup = MethodHandles.lookup();
44
45 MethodHandle m = lookup.findVirtual(
46 PlatformDependent0.UNSAFE.getClass(),
47 "invokeCleaner",
48 MethodType.methodType(void.class, ByteBuffer.class)).bindTo(PlatformDependent0.UNSAFE);
49 m.invokeExact(buffer);
50 return m;
51 } catch (Throwable cause) {
52 return cause;
53 }
54 });
55
56 if (maybeInvokeMethodHandle instanceof Throwable) {
57 invokeCleanerHandle = null;
58 error = (Throwable) maybeInvokeMethodHandle;
59 } else {
60 invokeCleanerHandle = (MethodHandle) maybeInvokeMethodHandle;
61 error = null;
62 }
63 } else {
64 invokeCleanerHandle = null;
65 error = new UnsupportedOperationException("sun.misc.Unsafe unavailable");
66 }
67 if (error == null) {
68 logger.debug("java.nio.ByteBuffer.cleaner(): available");
69 } else {
70 logger.debug("java.nio.ByteBuffer.cleaner(): unavailable", error);
71 }
72 INVOKE_CLEANER_HANDLE = invokeCleanerHandle;
73 }
74
75 static boolean isSupported() {
76 return INVOKE_CLEANER_HANDLE != null;
77 }
78
79 @Override
80 public void freeDirectBuffer(ByteBuffer buffer) {
81
82
83 if (System.getSecurityManager() == null) {
84 try {
85 INVOKE_CLEANER_HANDLE.invokeExact(buffer);
86 } catch (RuntimeException exception) {
87 throw exception;
88 } catch (Throwable throwable) {
89 PlatformDependent.throwException(throwable);
90 }
91 } else {
92 freeDirectBufferPrivileged(buffer);
93 }
94 }
95
96 private static void freeDirectBufferPrivileged(final ByteBuffer buffer) {
97 Exception error = AccessController.doPrivileged((PrivilegedAction<Exception>) () -> {
98 try {
99 INVOKE_CLEANER_HANDLE.invokeExact(PlatformDependent0.UNSAFE, buffer);
100 } catch (RuntimeException exception) {
101 return exception;
102 } catch (Throwable throwable) {
103 PlatformDependent.throwException(throwable);
104 }
105 return null;
106 });
107 if (error != null) {
108 PlatformDependent.throwException(error);
109 }
110 }
111 }