From 0f29b3ec7fd638341915f83384656e72dff868ec Mon Sep 17 00:00:00 2001 From: Uwe Schindler <uschindler@apache.org> Date: Sat, 20 Feb 2016 01:05:45 +0100 Subject: [PATCH] LUCENE-6989: Make casting to Runnable interface in cleaner hack easier to understand --- .../apache/lucene/store/MMapDirectory.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/lucene/core/src/java/org/apache/lucene/store/MMapDirectory.java b/lucene/core/src/java/org/apache/lucene/store/MMapDirectory.java index 348b36bab8f..ff16324c2b6 100644 --- a/lucene/core/src/java/org/apache/lucene/store/MMapDirectory.java +++ b/lucene/core/src/java/org/apache/lucene/store/MMapDirectory.java @@ -343,8 +343,8 @@ public class MMapDirectory extends FSDirectory { final Method m = directBufferClass.getMethod("cleaner"); m.setAccessible(true); - final MethodHandle directBufferCleanerMethod = lookup.unreflect(m); - final Class<?> cleanerClass = directBufferCleanerMethod.type().returnType(); + MethodHandle directBufferCleanerMethod = lookup.unreflect(m); + Class<?> cleanerClass = directBufferCleanerMethod.type().returnType(); final MethodHandle cleanMethod; if (Runnable.class.isAssignableFrom(cleanerClass)) { @@ -353,19 +353,22 @@ public class MMapDirectory extends FSDirectory { if (sm != null) { sm.checkPackageAccess("jdk.internal.ref"); } - cleanMethod = explicitCastArguments(lookup.findVirtual(Runnable.class, "run", methodType(void.class)), - methodType(void.class, cleanerClass)); + // cast return value of cleaner() to Runnable: + directBufferCleanerMethod = directBufferCleanerMethod.asType(directBufferCleanerMethod.type().changeReturnType(Runnable.class)); + cleanerClass = Runnable.class; + // lookup run() method on the interface instead of Cleaner: + cleanMethod = lookup.findVirtual(cleanerClass, "run", methodType(void.class)); } else { // can be either the old internal "sun.misc.Cleaner" or // the new Java 9 "java.lang.ref.Cleaner$Cleanable": cleanMethod = lookup.findVirtual(cleanerClass, "clean", methodType(void.class)); } - final MethodHandle nonNullTest = explicitCastArguments(lookup.findStatic(Objects.class, "nonNull", methodType(boolean.class, Object.class)), - methodType(boolean.class, cleanerClass)); - final MethodHandle noop = dropArguments(explicitCastArguments(constant(Void.class, null), methodType(void.class)), 0, cleanerClass); - final MethodHandle unmapper = explicitCastArguments(filterReturnValue(directBufferCleanerMethod, guardWithTest(nonNullTest, cleanMethod, noop)), - methodType(void.class, ByteBuffer.class)); + final MethodHandle nonNullTest = lookup.findStatic(Objects.class, "nonNull", methodType(boolean.class, Object.class)) + .asType(methodType(boolean.class, cleanerClass)); + final MethodHandle noop = dropArguments(constant(Void.class, null).asType(methodType(void.class)), 0, cleanerClass); + final MethodHandle unmapper = filterReturnValue(directBufferCleanerMethod, guardWithTest(nonNullTest, cleanMethod, noop)) + .asType(methodType(void.class, ByteBuffer.class)); return (BufferCleaner) (ByteBufferIndexInput parent, ByteBuffer buffer) -> { if (directBufferClass.isInstance(buffer)) {