All Downloads are FREE. Search and download functionalities are using the official Maven repository.

software.coley.llzip.util.CleanerUtil Maven / Gradle / Ivy

package software.coley.llzip.util;

import sun.misc.Unsafe;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;

/**
 * Utility to invoke cleaners in a {@link ByteBuffer}.
 *
 * @author xDark
 */
public final class CleanerUtil {
	private static final Method INVOKE_CLEANER;
	private static final Method GET_CLEANER;
	private static final boolean SUPPORTED;

	private CleanerUtil() {
	}

	/**
	 * Attempts to clean direct buffer.
	 *
	 * @param buffer
	 * 		Buffer to clean.
	 *
	 * @throws IllegalStateException
	 * 		If buffer is not direct, slice or duplicate, or
	 * 		cleaner failed to invoke.
	 */
	public static void invokeCleaner(ByteBuffer buffer) {
		if (!buffer.isDirect()) {
			throw new IllegalStateException("buffer is not direct");
		}
		if (!SUPPORTED) {
			return;
		}
		Method getCleaner = GET_CLEANER;
		Method invokeCleaner = INVOKE_CLEANER;
		try {
			if (getCleaner != null) {
				Object cleaner = getCleaner.invoke(buffer);
				if (cleaner == null) {
					throw new IllegalStateException("slice or duplicate");
				}
				invokeCleaner.invoke(cleaner);
			} else {
				invokeCleaner.invoke(UnsafeUtil.get(), buffer);
			}
		} catch (InvocationTargetException ex) {
			throw new IllegalStateException("Failed to invoke clean method", ex.getTargetException());
		} catch (IllegalAccessException ex) {
			throw new IllegalStateException("cleaner became inaccessible", ex);
		}
	}

	static {
		boolean supported = false;
		Method invokeCleaner;
		Method getCleaner = null;
		try {
			invokeCleaner = Unsafe.class.getDeclaredMethod("invokeCleaner", ByteBuffer.class);
			invokeCleaner.setAccessible(true);
			ByteBuffer tmp = ByteBuffer.allocateDirect(1);
			invokeCleaner.invoke(UnsafeUtil.get(), tmp);
			supported = true;
		} catch (NoSuchMethodException ignored) {
			supported = true;
			ByteBuffer tmp = ByteBuffer.allocateDirect(1);
			try {
				Class directBuffer = Class.forName("sun.nio.ch.DirectBuffer");
				getCleaner = directBuffer.getDeclaredMethod("cleaner");
				invokeCleaner = getCleaner.getReturnType().getDeclaredMethod("clean");
				invokeCleaner.setAccessible(true);
				getCleaner.setAccessible(true);
				invokeCleaner.invoke(getCleaner.invoke(tmp));
			} catch (Exception ignored1) {
				invokeCleaner = null;
				getCleaner = null;
				supported = false;
			}
		} catch (Exception ex) {
			invokeCleaner = null;
		}
		INVOKE_CLEANER = invokeCleaner;
		GET_CLEANER = getCleaner;
		SUPPORTED = supported;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy