1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.io.input;
18
19 import java.lang.reflect.Field;
20 import java.lang.reflect.Method;
21 import java.nio.ByteBuffer;
22
23
24
25
26
27
28
29
30
31
32
33
34
35 final class ByteBufferCleaner {
36
37 private interface Cleaner {
38 void clean(ByteBuffer buffer) throws ReflectiveOperationException;
39 }
40
41 private static final class Java8Cleaner implements Cleaner {
42
43 private final Method cleanerMethod;
44 private final Method cleanMethod;
45
46 private Java8Cleaner() throws ReflectiveOperationException, SecurityException {
47 cleanMethod = Class.forName("sun.misc.Cleaner").getMethod("clean");
48 cleanerMethod = Class.forName("sun.nio.ch.DirectBuffer").getMethod("cleaner");
49 }
50
51 @Override
52 public void clean(final ByteBuffer buffer) throws ReflectiveOperationException {
53 final Object cleaner = cleanerMethod.invoke(buffer);
54 if (cleaner != null) {
55 cleanMethod.invoke(cleaner);
56 }
57 }
58 }
59
60 private static final class Java9Cleaner implements Cleaner {
61
62 private final Object theUnsafe;
63 private final Method invokeCleaner;
64
65 private Java9Cleaner() throws ReflectiveOperationException, SecurityException {
66 final Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
67 final Field field = unsafeClass.getDeclaredField("theUnsafe");
68 field.setAccessible(true);
69 theUnsafe = field.get(null);
70 invokeCleaner = unsafeClass.getMethod("invokeCleaner", ByteBuffer.class);
71 }
72
73 @Override
74 public void clean(final ByteBuffer buffer) throws ReflectiveOperationException {
75 invokeCleaner.invoke(theUnsafe, buffer);
76 }
77 }
78
79 private static final Cleaner INSTANCE = getCleaner();
80
81
82
83
84
85
86
87 static void clean(final ByteBuffer buffer) {
88 try {
89 INSTANCE.clean(buffer);
90 } catch (final Exception e) {
91 throw new IllegalStateException("Failed to clean direct buffer.", e);
92 }
93 }
94
95 private static Cleaner getCleaner() {
96 try {
97 return new Java8Cleaner();
98 } catch (final Exception e) {
99 try {
100 return new Java9Cleaner();
101 } catch (final Exception e1) {
102 throw new IllegalStateException("Failed to initialize a Cleaner.", e);
103 }
104 }
105 }
106
107
108
109
110
111
112
113 static boolean isSupported() {
114 return INSTANCE != null;
115 }
116 }