/*
* Copyright 2004-2019 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.util;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import org.h2.engine.SysProperties;
Unsafe memory unmapper.
See Also: - NIO_CLEANER_HACK.NIO_CLEANER_HACK
/**
* Unsafe memory unmapper.
*
* @see SysProperties#NIO_CLEANER_HACK
*/
public final class MemoryUnmapper {
private static final boolean ENABLED;
private static final Object UNSAFE;
private static final Method INVOKE_CLEANER;
static {
boolean enabled = SysProperties.NIO_CLEANER_HACK;
Object unsafe = null;
Method invokeCleaner = null;
if (enabled) {
try {
Class<?> clazz = Class.forName("sun.misc.Unsafe");
Field field = clazz.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = field.get(null);
// This method exists only on Java 9 and later versions
invokeCleaner = clazz.getMethod("invokeCleaner", ByteBuffer.class);
} catch (ReflectiveOperationException e) {
// Java 7 or 8
unsafe = null;
// invokeCleaner can be only null here
} catch (Throwable e) {
// Should be a SecurityException, but catch everything to be
// safe
enabled = false;
unsafe = null;
// invokeCleaner can be only null here
}
}
ENABLED = enabled;
UNSAFE = unsafe;
INVOKE_CLEANER = invokeCleaner;
}
Tries to unmap memory for the specified byte buffer using Java internals in unsafe way if SysProperties.NIO_CLEANER_HACK
is enabled and access is not denied by a security manager. Params: - buffer –
mapped byte buffer
Returns: whether operation was successful
/**
* Tries to unmap memory for the specified byte buffer using Java internals
* in unsafe way if {@link SysProperties#NIO_CLEANER_HACK} is enabled and
* access is not denied by a security manager.
*
* @param buffer
* mapped byte buffer
* @return whether operation was successful
*/
public static boolean unmap(ByteBuffer buffer) {
if (!ENABLED) {
return false;
}
try {
if (INVOKE_CLEANER != null) {
// Java 9 or later
INVOKE_CLEANER.invoke(UNSAFE, buffer);
return true;
}
// Java 7 or 8
Method cleanerMethod = buffer.getClass().getMethod("cleaner");
cleanerMethod.setAccessible(true);
Object cleaner = cleanerMethod.invoke(buffer);
if (cleaner != null) {
Method clearMethod = cleaner.getClass().getMethod("clean");
clearMethod.invoke(cleaner);
}
return true;
} catch (Throwable e) {
return false;
}
}
private MemoryUnmapper() {
}
}