mirror of
https://github.com/elastic/logstash.git
synced 2025-04-24 22:57:16 -04:00
#6961 use codegen to invoke the appropriate ByteBuffer Cleaner depending on JVM version
Fixes #8568
This commit is contained in:
parent
f03f1b7775
commit
753cd9e104
4 changed files with 102 additions and 12 deletions
|
@ -0,0 +1,72 @@
|
|||
package org.logstash;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import org.codehaus.janino.ClassBodyEvaluator;
|
||||
import org.logstash.ackedqueue.io.ByteBufferCleaner;
|
||||
|
||||
/**
|
||||
* Logic around ensuring compatibility with Java 8 and 9 simultaneously.
|
||||
*/
|
||||
public final class LogstashJavaCompat {
|
||||
|
||||
/**
|
||||
* True if current JVM is a Java 9 implementation.
|
||||
*/
|
||||
public static final boolean IS_JAVA_9_OR_GREATER = isAtLeastJava9();
|
||||
|
||||
/**
|
||||
* Sets up an appropriate implementation of {@link ByteBufferCleaner} depending no whether or
|
||||
* not the current JVM is a Java 9 implementation.
|
||||
* @return ByteBufferCleaner
|
||||
*/
|
||||
public static ByteBufferCleaner setupBytebufferCleaner() {
|
||||
final ClassBodyEvaluator se = new ClassBodyEvaluator();
|
||||
final Collection<String> imports = new ArrayList<>();
|
||||
imports.add("java.nio.MappedByteBuffer");
|
||||
final String cleanerCode;
|
||||
final String ctorCode;
|
||||
final String fieldsCode;
|
||||
if (isAtLeastJava9()) {
|
||||
imports.add("sun.misc.Unsafe");
|
||||
imports.add("java.lang.reflect.Field");
|
||||
cleanerCode = "unsafe.invokeCleaner(buffer);";
|
||||
ctorCode = "Field unsafeField = Unsafe.class.getDeclaredField(\"theUnsafe\");" +
|
||||
"unsafeField.setAccessible(true);" +
|
||||
"unsafe = (Unsafe) unsafeField.get(null);";
|
||||
fieldsCode = "private final Unsafe unsafe;";
|
||||
} else {
|
||||
imports.add("sun.misc.Cleaner");
|
||||
imports.add("sun.nio.ch.DirectBuffer");
|
||||
cleanerCode = "Cleaner c=((DirectBuffer)buffer).cleaner();if(c != null){c.clean();}";
|
||||
ctorCode = "";
|
||||
fieldsCode = "";
|
||||
}
|
||||
se.setImplementedInterfaces(new Class[]{ByteBufferCleaner.class});
|
||||
se.setClassName("ByteBufferCleanerImpl");
|
||||
se.setDefaultImports(imports.toArray(new String[0]));
|
||||
try {
|
||||
return (ByteBufferCleaner) se.createInstance(
|
||||
new StringReader(String.format(
|
||||
"%s public ByteBufferCleanerImpl() throws Exception{%s} public void clean(MappedByteBuffer buffer){%s}",
|
||||
fieldsCode, ctorCode, cleanerCode
|
||||
))
|
||||
);
|
||||
} catch (final Exception ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies whether we're running on Java 9 by parsing the first component of the
|
||||
* {@code "java.version"} system property. For Java 9 this value is assumed to start with a
|
||||
* {@code "9"}.
|
||||
* @return True iff running on Java 9
|
||||
*/
|
||||
private static boolean isAtLeastJava9() {
|
||||
final String version = System.getProperty("java.version");
|
||||
final int end = version.indexOf('.');
|
||||
return Integer.parseInt(version.substring(0, end > 0 ? end : version.length())) >= 9;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package org.logstash.ackedqueue.io;
|
||||
|
||||
import java.nio.MappedByteBuffer;
|
||||
|
||||
/**
|
||||
* Function that forces garbage collection of a {@link MappedByteBuffer}.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ByteBufferCleaner {
|
||||
|
||||
/**
|
||||
* Forces garbage collection of given buffer.
|
||||
* @param buffer ByteBuffer to GC
|
||||
*/
|
||||
void clean(MappedByteBuffer buffer);
|
||||
}
|
|
@ -1,8 +1,5 @@
|
|||
package org.logstash.ackedqueue.io;
|
||||
|
||||
import sun.misc.Cleaner;
|
||||
import sun.nio.ch.DirectBuffer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
|
@ -10,12 +7,16 @@ import java.nio.MappedByteBuffer;
|
|||
import java.nio.channels.FileChannel;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.logstash.LogstashJavaCompat;
|
||||
// TODO: this essentially a copy of ByteBufferPageIO and should be DRY'ed - temp impl to test file based stress test
|
||||
|
||||
@SuppressWarnings("sunapi")
|
||||
public class MmapPageIO extends AbstractByteBufferPageIO {
|
||||
|
||||
/**
|
||||
* Cleaner function for forcing unmapping of backing {@link MmapPageIO#buffer}.
|
||||
*/
|
||||
private static final ByteBufferCleaner BUFFER_CLEANER =
|
||||
LogstashJavaCompat.setupBytebufferCleaner();
|
||||
|
||||
private File file;
|
||||
|
||||
private FileChannel channel;
|
||||
|
@ -108,11 +109,7 @@ public class MmapPageIO extends AbstractByteBufferPageIO {
|
|||
public void close() throws IOException {
|
||||
if (this.buffer != null) {
|
||||
this.buffer.force();
|
||||
|
||||
// calling the cleaner() method releases resources held by this direct buffer which would be held until GC otherwise.
|
||||
// see https://github.com/elastic/logstash/pull/6740
|
||||
Cleaner cleaner = ((DirectBuffer) this.buffer).cleaner();
|
||||
if (cleaner != null) { cleaner.clean(); }
|
||||
BUFFER_CLEANER.clean(buffer);
|
||||
|
||||
}
|
||||
if (this.channel != null) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.logstash.instruments.monitors;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.logstash.LogstashJavaCompat;
|
||||
import org.logstash.instrument.monitors.MemoryMonitor;
|
||||
|
||||
import java.util.Map;
|
||||
|
@ -17,7 +18,11 @@ public class MemoryMonitorTest {
|
|||
public void testEachHeapSpaceRepresented() {
|
||||
Map<String, Map<String, Object>> heap = MemoryMonitor.detect(MemoryMonitor.Type.All).getHeap();
|
||||
assertThat(heap, notNullValue());
|
||||
assertThat(heap.keySet(), hasItems("PS Survivor Space", "PS Old Gen", "PS Eden Space"));
|
||||
if (LogstashJavaCompat.IS_JAVA_9_OR_GREATER) {
|
||||
assertThat(heap.keySet(), hasItems("G1 Old Gen", "G1 Survivor Space", "G1 Eden Space"));
|
||||
} else {
|
||||
assertThat(heap.keySet(), hasItems("PS Survivor Space", "PS Old Gen", "PS Eden Space"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue