Last active
September 8, 2020 15:55
-
-
Save maketubo/5f167b25b42a18eee83c29867172db6e to your computer and use it in GitHub Desktop.
My CleanerUtil Implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CleanerUtil { | |
private static MethodHandle methodHandle; | |
private static MethodHandle cleanerMethodHandle; | |
private static MethodHandle clean; | |
static { | |
MethodHandles.Lookup lookup = MethodHandles.publicLookup(); | |
if (isJava9OrLater()) { | |
// Java 9 branch | |
// Unsafe.theUnsafe.invokeCleaner(byteBuffer) | |
try { | |
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe"); | |
Field instanceField = unsafeClass.getDeclaredField("theUnsafe"); | |
if (!instanceField.isAccessible()) { | |
instanceField.setAccessible(true); | |
} | |
Object unsafe = instanceField.get(null); | |
Method invokeCleaner = unsafeClass.getDeclaredMethod("invokeCleaner", ByteBuffer.class); | |
methodHandle = lookup.unreflect(invokeCleaner).bindTo(unsafe); | |
} catch (Exception e) { | |
throw new IllegalStateException("could not get invokeCleaner method handle", e); | |
} catch (Throwable throwable) { | |
throwable.printStackTrace(); | |
} | |
} else { | |
// Java 8 branch | |
// sun.misc.Cleaner cleaner = ((sun.nio.ch.DirectBuffer) buffer).cleaner(); | |
// cleaner.clean(); | |
try { | |
Class<?> bufferInterface = Class.forName("java.nio.DirectByteBuffer"); | |
Method cleanerMethod = bufferInterface.getDeclaredMethod("cleaner"); | |
if (!cleanerMethod.isAccessible()) { | |
cleanerMethod.setAccessible(true); | |
} | |
Class<?> cleanerClass = Class.forName("sun.misc.Cleaner"); | |
Method cleanMethod = cleanerClass.getDeclaredMethod("clean"); // should be accessible | |
cleanerMethodHandle = lookup.unreflect(cleanerMethod); | |
clean = lookup.unreflect(cleanMethod); | |
} catch (ReflectiveOperationException e) { | |
throw new IllegalStateException("could not get cleaner clean method handle", e); | |
} catch (Throwable throwable) { | |
throwable.printStackTrace(); | |
} | |
} | |
} | |
public static boolean isJava9OrLater() { | |
try { | |
Class.forName("java.lang.Runtime$Version"); | |
return true; | |
} catch (ClassNotFoundException e) { | |
return false; | |
} | |
} | |
public static void clean(Object buffer) { | |
try { | |
if (isJava9OrLater()) { | |
methodHandle.invokeExact((ByteBuffer)buffer); | |
} else { | |
clean.invoke(cleanerMethodHandle.invoke((ByteBuffer)buffer)); | |
} | |
} catch (Throwable throwable) { | |
throwable.printStackTrace(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment