package net.openhft.chronicle.core.cleaner.impl.reflect;

import net.openhft.chronicle.core.Jvm;
import net.openhft.chronicle.core.cleaner.spi.ByteBufferCleanerService;
import sun.misc.Cleaner;
import sun.nio.ch.DirectBuffer;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.nio.ByteBuffer;

public final class ReflectionBasedByteBufferCleanerService implements ByteBufferCleanerService {
    private static final String JDK8_CLEANER_CLASS_NAME = "sun.misc.Cleaner";
    private static final String JDK9_CLEANER_CLASS_NAME = "jdk.internal.ref.Cleaner";

    private static final MethodHandle cleanerMethod, cleanMethod;

    static {
        MethodHandles.Lookup lookup = MethodHandles.lookup();
        final String cleanerClassname = Jvm.isJava9Plus() ?
                JDK9_CLEANER_CLASS_NAME : JDK8_CLEANER_CLASS_NAME;
        try {
            cleanerMethod = lookup.findVirtual(DirectBuffer.class, "cleaner", MethodType.methodType(Cleaner.class));
            cleanMethod = lookup.findVirtual(Class.forName(cleanerClassname), "clean", MethodType.methodType(void.class));
        } catch (NoSuchMethodException | ClassNotFoundException | IllegalAccessException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    @Override
    public void clean(final ByteBuffer buffer) {
        try {
            Object cleaner = cleanerMethod.invoke((DirectBuffer) buffer);
            cleanMethod.invoke(cleaner);
        } catch (Throwable throwable) {
            Jvm.rethrow(throwable);
        }
    }

    @Override
    public int impact() {
        return SOME_IMPACT;
    }
}

@@ -899,32 +899,107 @@
 ;%0A        try %7B%0A
+            final Class%3C?%3E cleanerClass = Class.forName(cleanerClassname);%0A
             clea
@@ -1086,17 +1086,16 @@
 ype(
-C
+c
 leaner
-.c
+C
 lass
@@ -1143,30 +1143,16 @@
 Virtual(
-Class.forName(
 cleanerC
@@ -1155,21 +1155,16 @@
 nerClass
-name)
 , %22clean

Fix Java 11