// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.io;

import com.intellij.ReviseWhenPortedToJDK;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.SystemInfoRt;
import com.intellij.util.concurrency.AtomicFieldUpdater;
import org.jetbrains.annotations.NotNull;

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

public final class ByteBufferUtil {
  /**
   * Please use with care. In most cases leaving the job to the GC is enough.
   */
  @ReviseWhenPortedToJDK("11")
  public static boolean cleanBuffer(@NotNull ByteBuffer buffer) {
    if (!buffer.isDirect()) return true;

    if (SystemInfoRt.IS_AT_LEAST_JAVA9) {
      // in Java 9+, the "official" dispose method is sun.misc.Unsafe#invokeCleaner
      Object unsafe = AtomicFieldUpdater.getUnsafe();
      try {
        MethodType type = MethodType.methodType(void.class, ByteBuffer.class);
        @SuppressWarnings("JavaLangInvokeHandleSignature") MethodHandle handle = MethodHandles.lookup().findVirtual(unsafe.getClass(), "invokeCleaner", type);
        handle.invoke(unsafe, buffer);
        return true;
      }
      catch (Throwable t) {
        Logger.getInstance(ByteBufferUtil.class).warn(t);
        return false;
      }
    }
    return false;
  }
}
@@ -1433,27 +1433,621 @@
   %7D%0A    
-return false;
+else %7B%0A      //todo%5Bnik%5D: check we really need this for Java 8 and older%0A      try %7B%0A        Class%3C?%3E directBufferClass = Class.forName(%22sun.nio.ch.DirectBuffer%22);%0A        Class%3C?%3E cleanerClass = Class.forName(%22sun.misc.Cleaner%22);%0A        Object cleaner = directBufferClass.getDeclaredMethod(%22cleaner%22).invoke(buffer);%0A        if (cleaner != null) %7B%0A          cleanerClass.getDeclaredMethod(%22clean%22).invoke(cleaner);  // already cleaned otherwise%0A        %7D%0A        return true;%0A      %7D%0A      catch (Exception e) %7B%0A        Logger.getInstance(ByteBufferUtil.class).warn(e);%0A        return false;%0A      %7D%0A    %7D
 %0A  %7D%0A%7D

add implementation for Java 8