re OpenHFT/Chronicle-Map#134 Reflection based access to Cleaner compatible with 8 and 9+ JDKs.

This commit is contained in:
Paweł Dąbrowski
2018-04-23 17:33:43 +02:00
parent e7c7dd8975
commit f2064f4db4
4 changed files with 78 additions and 2 deletions
@@ -25,6 +25,8 @@ import net.openhft.chronicle.core.Maths;
import net.openhft.chronicle.core.OS;
import net.openhft.chronicle.hash.*;
import net.openhft.chronicle.hash.impl.util.BuildVersion;
import net.openhft.chronicle.hash.impl.util.Cleaner;
import net.openhft.chronicle.hash.impl.util.CleanerUtils;
import net.openhft.chronicle.hash.impl.util.jna.PosixMsync;
import net.openhft.chronicle.hash.impl.util.jna.WindowsMsync;
import net.openhft.chronicle.hash.serialization.DataAccess;
@@ -38,7 +40,6 @@ import net.openhft.chronicle.wire.Marshallable;
import net.openhft.chronicle.wire.WireIn;
import net.openhft.chronicle.wire.WireOut;
import org.jetbrains.annotations.NotNull;
import sun.misc.Cleaner;
import java.io.Closeable;
import java.io.File;
@@ -465,7 +466,7 @@ public abstract class VanillaChronicleHash<K,
}
public void registerCleaner() {
this.cleaner = Cleaner.create(this, resources);
this.cleaner = CleanerUtils.createCleaner(this, resources);
}
public void addToOnExitHook() {
@@ -0,0 +1,7 @@
package net.openhft.chronicle.hash.impl.util;
public interface Cleaner {
void clean();
}
@@ -0,0 +1,45 @@
package net.openhft.chronicle.hash.impl.util;
import net.openhft.chronicle.core.Jvm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class CleanerUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(CleanerUtils.class);
private static final Method CREATE_METHOD;
private static final Method CLEAN_METHOD;
static {
try {
Class cleanerClass = Class.forName(Jvm.isJava9Plus() ? "jdk.internal.ref.Cleaner" : "sun.misc.Cleaner");
CREATE_METHOD = cleanerClass.getDeclaredMethod("create", Object.class, Runnable.class);
CLEAN_METHOD = cleanerClass.getDeclaredMethod("clean");
} catch (ClassNotFoundException | NoSuchMethodException e) {
LOGGER.error("Unable to initialise CleanerUtils", e);
throw new RuntimeException(e);
}
}
public static Cleaner createCleaner(Object ob, Runnable thunk) {
try {
Object cleanerInstance = CREATE_METHOD.invoke(null, ob, thunk);
return () -> doClean(cleanerInstance);
} catch (IllegalAccessException | InvocationTargetException e) {
LOGGER.error("Unable to create cleaner", e);
throw new RuntimeException(e);
}
}
private static void doClean(Object cleanerInstance) {
try {
CLEAN_METHOD.invoke(cleanerInstance);
} catch (IllegalAccessException | InvocationTargetException e) {
LOGGER.warn("Failed to clean buffer", e);
}
}
}