summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/java/com/jogamp/common/nio/Buffers.java54
-rw-r--r--src/junit/com/jogamp/common/nio/TestBuffers.java (renamed from src/junit/com/jogamp/common/nio/BuffersTest.java)10
-rw-r--r--src/junit/com/jogamp/common/nio/TestByteBufferCopyStream.java11
-rw-r--r--src/junit/com/jogamp/common/nio/TestCachedBufferFactory.java (renamed from src/junit/com/jogamp/common/nio/CachedBufferFactoryTest.java)6
4 files changed, 68 insertions, 13 deletions
diff --git a/src/java/com/jogamp/common/nio/Buffers.java b/src/java/com/jogamp/common/nio/Buffers.java
index fb23627..5125ee8 100644
--- a/src/java/com/jogamp/common/nio/Buffers.java
+++ b/src/java/com/jogamp/common/nio/Buffers.java
@@ -39,6 +39,7 @@
*/
package com.jogamp.common.nio;
+import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.Buffer;
import java.nio.ByteBuffer;
@@ -56,6 +57,7 @@ import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.common.util.ValueConv;
import jogamp.common.Debug;
+import jogamp.common.os.PlatformPropsImpl;
/**
* Utility methods allowing easy {@link java.nio.Buffer} manipulations.
@@ -1165,22 +1167,42 @@ public class Buffers {
* Access to NIO {@link sun.misc.Cleaner}, allowing caller to deterministically clean a given {@link sun.nio.ch.DirectBuffer}.
*/
public static class Cleaner {
+ private static final Object theUnsafe;
private static final Method mbbCleaner;
private static final Method cClean;
private static final boolean hasCleaner;
/** OK to be lazy on thread synchronization, just for early out **/
private static volatile boolean cleanerError;
static {
+ final Object[] _theUnsafe = { null };
final Method[] _mbbCleaner = { null };
final Method[] _cClean = { null };
if( AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
try {
- _mbbCleaner[0] = ReflectionUtil.getMethod("sun.nio.ch.DirectBuffer", "cleaner", null, Buffers.class.getClassLoader());
- _mbbCleaner[0].setAccessible(true);
- _cClean[0] = Class.forName("sun.misc.Cleaner").getMethod("clean");
- _cClean[0].setAccessible(true);
+ if(PlatformPropsImpl.JAVA_9) {
+ // Using: sun.misc.Unsafe { public void invokeCleaner(java.nio.ByteBuffer directBuffer); }
+ _mbbCleaner[0] = null;
+ final Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
+ {
+ final Field f = unsafeClass.getDeclaredField("theUnsafe");
+ f.setAccessible(true);
+ _theUnsafe[0] = f.get(null);
+ }
+ _cClean[0] = unsafeClass.getMethod("invokeCleaner", java.nio.ByteBuffer.class);
+ _cClean[0].setAccessible(true);
+ } else {
+ _mbbCleaner[0] = ReflectionUtil.getMethod("sun.nio.ch.DirectBuffer", "cleaner", null, Buffers.class.getClassLoader());
+ _mbbCleaner[0].setAccessible(true);
+ final Class<?> cleanerType = _mbbCleaner[0].getReturnType();
+ // Java >= 9: jdk.internal.ref.Cleaner (NOT accessible!)
+ // "Unable to make public void jdk.internal.ref.Cleaner.clean() accessible:
+ // module java.base does not "exports jdk.internal.ref" to unnamed module"
+ // Java <= 8: sun.misc.Cleaner OK
+ _cClean[0] = cleanerType.getMethod("clean");
+ _cClean[0].setAccessible(true);
+ }
return Boolean.TRUE;
} catch(final Throwable t) {
if( DEBUG ) {
@@ -1189,27 +1211,43 @@ public class Buffers {
}
return Boolean.FALSE;
} } } ).booleanValue() ) {
+ theUnsafe = _theUnsafe[0];
mbbCleaner = _mbbCleaner[0];
cClean = _cClean[0];
- hasCleaner = null != mbbCleaner && null != cClean;
+ hasCleaner = PlatformPropsImpl.JAVA_9 ? null != theUnsafe && null != cClean : null != mbbCleaner && null != cClean;
} else {
+ theUnsafe = null;
mbbCleaner = null;
cClean = null;
hasCleaner = false;
}
cleanerError = !hasCleaner;
+ if( DEBUG ) {
+ System.err.print("Buffers.Cleaner.init: hasCleaner: "+hasCleaner+", cleanerError "+cleanerError);
+ if( null != mbbCleaner ) {
+ System.err.print(", using Cleaner class: "+mbbCleaner.getReturnType().getName());
+ }
+ if( null != theUnsafe ) {
+ System.err.print(", using sun.misc.Unsafe::invokeCleaner(..);");
+ }
+ System.err.println();
+ }
}
/**
* If {@code b} is an direct NIO buffer, i.e {@link sun.nio.ch.DirectBuffer},
* calls it's {@link sun.misc.Cleaner} instance {@code clean()} method.
* @return {@code true} if successful, otherwise {@code false}.
*/
- public static boolean clean(final Buffer b) {
- if( !hasCleaner || cleanerError || !b.isDirect() ) {
+ public static boolean clean(final ByteBuffer bb) {
+ if( !hasCleaner || cleanerError || !bb.isDirect() ) {
return false;
}
try {
- cClean.invoke(mbbCleaner.invoke(b));
+ if( PlatformPropsImpl.JAVA_9 ) {
+ cClean.invoke(theUnsafe, bb);
+ } else {
+ cClean.invoke(mbbCleaner.invoke(bb));
+ }
return true;
} catch(final Throwable t) {
cleanerError = true;
diff --git a/src/junit/com/jogamp/common/nio/BuffersTest.java b/src/junit/com/jogamp/common/nio/TestBuffers.java
index c267100..89b5671 100644
--- a/src/junit/com/jogamp/common/nio/BuffersTest.java
+++ b/src/junit/com/jogamp/common/nio/TestBuffers.java
@@ -53,7 +53,7 @@ import org.junit.FixMethodOrder;
import org.junit.runners.MethodSorters;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-public class BuffersTest extends SingletonJunitCase {
+public class TestBuffers extends SingletonJunitCase {
@Test
public void test01PositionLimitCapacityAfterArrayAllocation() {
@@ -156,8 +156,14 @@ public class BuffersTest extends SingletonJunitCase {
assertEquals(42, onetwothree.get(2));
}
+ @Test
+ public void test20Cleaner() {
+ final ByteBuffer byteBuffer = Buffers.newDirectByteBuffer(1024);
+ Buffers.Cleaner.clean(byteBuffer);
+ }
+
public static void main(final String args[]) throws IOException {
- final String tstname = BuffersTest.class.getName();
+ final String tstname = TestBuffers.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
}
diff --git a/src/junit/com/jogamp/common/nio/TestByteBufferCopyStream.java b/src/junit/com/jogamp/common/nio/TestByteBufferCopyStream.java
index 9524e91..aef0d3e 100644
--- a/src/junit/com/jogamp/common/nio/TestByteBufferCopyStream.java
+++ b/src/junit/com/jogamp/common/nio/TestByteBufferCopyStream.java
@@ -52,6 +52,8 @@ public class TestByteBufferCopyStream extends SingletonJunitCase {
final MappedByteBufferInputStream.CacheMode srcCacheMode, final int srcSliceShift,
final String dstFileName,
final MappedByteBufferInputStream.CacheMode dstCacheMode, final int dstSliceShift ) throws IOException {
+ System.err.println("Test: source[CacheMode "+srcCacheMode+", SliceShift "+srcSliceShift+"]");
+ System.err.println(" destin[CacheMode "+dstCacheMode+", SliceShift "+dstSliceShift+"]");
final Runtime runtime = Runtime.getRuntime();
final long[] usedMem0 = { 0 };
final long[] freeMem0 = { 0 };
@@ -60,6 +62,7 @@ public class TestByteBufferCopyStream extends SingletonJunitCase {
final String prefix = "test "+String.format(TestByteBufferInputStream.PrintPrecision+" MiB", size/TestByteBufferInputStream.MIB);
TestByteBufferInputStream.dumpMem(prefix+" before", runtime, -1, -1, usedMem0, freeMem0 );
+ final long t0 = Platform.currentTimeMillis();
final File srcFile = new File(srcFileName);
srcFile.delete();
srcFile.createNewFile();
@@ -72,6 +75,7 @@ public class TestByteBufferCopyStream extends SingletonJunitCase {
_input.close();
input = new RandomAccessFile(srcFile, "r");
}
+ final long t1 = Platform.currentTimeMillis();
final MappedByteBufferInputStream mis = new MappedByteBufferInputStream(input.getChannel(),
FileChannel.MapMode.READ_ONLY,
srcCacheMode,
@@ -131,12 +135,19 @@ public class TestByteBufferCopyStream extends SingletonJunitCase {
output.close();
srcFile.delete();
dstFile.delete();
+ final long t5 = Platform.currentTimeMillis();
TestByteBufferInputStream.dumpMem(prefix+" after ", runtime, usedMem0[0], freeMem0[0], usedMem1, freeMem1 );
System.gc();
+ final long t6 = Platform.currentTimeMillis();
try {
Thread.sleep(500);
} catch (final InterruptedException e) { }
TestByteBufferInputStream.dumpMem(prefix+" gc'ed ", runtime, usedMem0[0], freeMem0[0], usedMem1, freeMem1 );
+ System.err.println("Performance Stats: ");
+ System.err.printf("- File-Create %6d ms\n", t1-t0);
+ System.err.printf("- File-Copy %6d ms\n", t5-t1);
+ System.err.printf("- GC %6d ms\n", t6-t5);
+ System.err.printf("- Total %6d ms\n", t6-t0);
}
if( null != ioe || null != oome ) {
if( null != oome ) {
diff --git a/src/junit/com/jogamp/common/nio/CachedBufferFactoryTest.java b/src/junit/com/jogamp/common/nio/TestCachedBufferFactory.java
index 6b9409f..6ed1b91 100644
--- a/src/junit/com/jogamp/common/nio/CachedBufferFactoryTest.java
+++ b/src/junit/com/jogamp/common/nio/TestCachedBufferFactory.java
@@ -55,7 +55,7 @@ import org.junit.FixMethodOrder;
import org.junit.runners.MethodSorters;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-public class CachedBufferFactoryTest extends SingletonJunitCase {
+public class TestCachedBufferFactory extends SingletonJunitCase {
private final int BUFFERCOUNT = 120;
@@ -210,7 +210,7 @@ public class CachedBufferFactoryTest extends SingletonJunitCase {
public static void main(final String[] args) {
- CachedBufferFactoryTest test = new CachedBufferFactoryTest();
+ TestCachedBufferFactory test = new TestCachedBufferFactory();
out.print("warmup...");
Object obj = null;
@@ -221,7 +221,7 @@ public class CachedBufferFactoryTest extends SingletonJunitCase {
}
out.println("done");
- test = new CachedBufferFactoryTest();
+ test = new TestCachedBufferFactory();
gc();
for (int i = 0; i < 10; i++) {