host.anzo.commons.unsafe.ByteBufferCleaner Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of commons-core Show documentation
Show all versions of commons-core Show documentation
Commons library to make me happy.
package host.anzo.commons.unsafe;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
/**
* @author ANZO
* @since 6/30/2023
*/
public class ByteBufferCleaner {
private static final Cleaner INSTANCE = getCleaner();
/**
* Releases memory held by the given {@link ByteBuffer}.
* @param buffer to release.
* @throws IllegalStateException on internal failure.
*/
public static void clean(final ByteBuffer buffer) {
try {
INSTANCE.clean(buffer);
}
catch (final Exception e) {
throw new IllegalStateException("Failed to clean direct buffer.", e);
}
}
private static Cleaner getCleaner() {
try {
return new Java8Cleaner();
}
catch (final Exception e) {
try {
return new Java9Cleaner();
}
catch (final Exception e1) {
throw new IllegalStateException("Failed to initialize a Cleaner.", e);
}
}
}
private interface Cleaner {
void clean(ByteBuffer buffer) throws ReflectiveOperationException;
}
private static class Java8Cleaner implements Cleaner {
private final Method cleanerMethod;
private final Method cleanMethod;
private Java8Cleaner() throws ReflectiveOperationException, SecurityException {
cleanMethod = Class.forName("sun.misc.Cleaner").getMethod("clean");
cleanerMethod = Class.forName("sun.nio.ch.DirectBuffer").getMethod("cleaner");
}
@Override
public void clean(final ByteBuffer buffer) throws ReflectiveOperationException {
final Object cleaner = cleanerMethod.invoke(buffer);
if (cleaner != null) {
cleanMethod.invoke(cleaner);
}
}
}
private static class Java9Cleaner implements Cleaner {
private final Object theUnsafe;
private final Method invokeCleaner;
private Java9Cleaner() throws ReflectiveOperationException, SecurityException {
final Class> unsafeClass = Class.forName("sun.misc.Unsafe");
final Field field = unsafeClass.getDeclaredField("theUnsafe");
field.setAccessible(true);
theUnsafe = field.get(null);
invokeCleaner = unsafeClass.getMethod("invokeCleaner", ByteBuffer.class);
}
@Override
public void clean(final ByteBuffer buffer) throws ReflectiveOperationException {
invokeCleaner.invoke(theUnsafe, buffer);
}
}
}