Merge pull request #150 from codewise/master

re OpenHFT/Chronicle-Map#134 Reflection based access to Cleaner compa…
This commit is contained in:
Dmitry Pisklov
2018-04-24 18:41:51 +01:00
committed by GitHub
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);
}
}
}
@@ -0,0 +1,23 @@
package net.openhft.chronicle.hash.impl.util;
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertTrue;
public class CleanerUtilsTest {
@Test
public void testClean() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
Object ob = new Object();
Cleaner cleaner = CleanerUtils.createCleaner(ob, latch::countDown);
cleaner.clean();
assertTrue(latch.await(1, TimeUnit.SECONDS));
}
}