Clean up Direct Memory Region Files Fix for different Java versions

Java 9+ doesn't allow using the exposed cleanup method, but added
a new method on Unsafe to do it.

So have to detect java version and use the appropriate strategy.
This commit is contained in:
Aikar 2020-05-04 02:19:38 -04:00
parent 55e3501967
commit a4ed58a9ab
No known key found for this signature in database
GPG key ID: 401ADFC9891FAAFE

View file

@ -1,4 +1,4 @@
From b649a81d4edeb173e725b72ad931a7f0a81b6714 Mon Sep 17 00:00:00 2001
From 8fdbc0b6bb68ba8e6f6ce8035c9936e3922808f0 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Mon, 4 May 2020 00:38:13 -0400
Subject: [PATCH] Cleanup Region Files Direct Memory on close
@ -10,7 +10,7 @@ Finalizers have no guarantee on when they will be ran, and since this is
old generation memory, it might be a while before its called.
diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java
index df728e2c0a..c565307a58 100644
index df728e2c0a..20927d55c6 100644
--- a/src/main/java/net/minecraft/server/RegionFile.java
+++ b/src/main/java/net/minecraft/server/RegionFile.java
@@ -30,7 +30,7 @@ public class RegionFile implements AutoCloseable {
@ -22,14 +22,66 @@ index df728e2c0a..c565307a58 100644
private final IntBuffer g;
private final IntBuffer h;
private final RegionFileBitSet freeSectors;
@@ -403,6 +403,7 @@ public class RegionFile implements AutoCloseable {
@@ -403,10 +403,59 @@ public class RegionFile implements AutoCloseable {
}
} finally { // Paper start - Prevent regionfiles from being closed during use
this.fileLock.unlock();
+ if (getFileBuffer() instanceof sun.nio.ch.DirectBuffer) ((sun.nio.ch.DirectBuffer) getFileBuffer()).cleaner().clean(); // Paper - clean up direct buffers on close
+ if (getFileBuffer().isDirect()) cleanDirectByteBuffer(getFileBuffer()); // Paper - clean up direct buffers on close
}
} // Paper end
}
+ // Paper start
+ private static int getVersion() {
+ String version = System.getProperty("java.version");
+ if(version.startsWith("1.")) {
+ version = version.substring(2, 3);
+ } else {
+ int dot = version.indexOf(".");
+ if(dot != -1) { version = version.substring(0, dot); }
+ } return Integer.parseInt(version);
+ }
+ static java.lang.reflect.Method unsafeClean;
+ static sun.misc.Unsafe unsafe = com.destroystokyo.paper.utils.UnsafeUtils.getUnsafe();
+ static java.util.function.Consumer<ByteBuffer> cleaner;
+ static {
+ try {
+ if (unsafe != null) {
+ unsafeClean = unsafe.getClass().getMethod("invokeCleaner", ByteBuffer.class);
+ if (unsafeClean != null) {
+ cleaner = (buf) -> {
+ try {
+ unsafeClean.invoke(unsafe, buf);
+ } catch (Exception ex) {
+ com.destroystokyo.paper.util.SneakyThrow.sneaky(ex);
+ }
+ };
+ LOGGER.info("[RegionFile] Using Java 9+ invokeCleaner DirectByteBuffer cleanup method");
+ }
+ }
+ } catch (java.lang.NoSuchMethodException e) {}
+ if (cleaner == null && getVersion() <= 8) {
+ cleaner = (buf) -> {
+ ((sun.nio.ch.DirectBuffer) buf).cleaner().clean();
+ };
+ LOGGER.info("[RegionFile] Using Java 8 DirectByteBuffer cleanup method");
+ }
+ }
+ public static void cleanDirectByteBuffer(ByteBuffer toBeDestroyed) {
+ try {
+ if (cleaner != null) {
+ cleaner.accept(toBeDestroyed);
+ }
+ } catch (Exception ex) {
+ LOGGER.warn("Failed automatically cleaning DirectByteBuffer");
+ ex.printStackTrace();
+ cleaner = null;
+ }
+ }
+ // Paper end
private void c() throws IOException {
int i = (int) this.dataFile.size();
--
2.26.2