aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2017-02-22 15:00:05 +0100
committerSven Gothel <[email protected]>2017-02-22 15:00:05 +0100
commit6833dfa977c282a9b016ede99fdaa46eb5b06444 (patch)
tree17a2f914274625f31990c8bd8261dcef20782121
parent574be76b4c4a396d1de7c8ead1fcbfed1fbac1ec (diff)
Factor out Cleaner access for general use (Cleaning up NIO DirectBuffer)
-rwxr-xr-xmake/scripts/runtest.sh5
-rw-r--r--src/java/com/jogamp/common/nio/Buffers.java71
-rw-r--r--src/java/com/jogamp/common/nio/MappedByteBufferInputStream.java59
3 files changed, 78 insertions, 57 deletions
diff --git a/make/scripts/runtest.sh b/make/scripts/runtest.sh
index a35220e..924ee93 100755
--- a/make/scripts/runtest.sh
+++ b/make/scripts/runtest.sh
@@ -63,6 +63,7 @@ X_ARGS="-Drootrel.build=$ROOTREL_BUILD -Dgluegen.root=$GLUEGEN_ROOT"
#D_ARGS="-Djogamp.debug.IOUtil -Djogamp.debug.IOUtil.Exe -Djogamp.debug.IOUtil.Exe.NoStream"
#D_ARGS="-Djogamp.debug.IOUtil -Djogamp.debug.IOUtil.Exe"
#D_ARGS="-Djogamp.debug.ByteBufferInputStream"
+D_ARGS="-Djogamp.debug.Buffers"
#D_ARGS="-Djogamp.debug.Bitstream"
#D_ARGS="-Djogamp.debug=all"
#D_ARGS="-Djogamp.debug.Logging"
@@ -92,7 +93,7 @@ function onetest() {
#onetest com.jogamp.common.util.TestSystemPropsAndEnvs 2>&1 | tee -a $LOG
#onetest com.jogamp.common.util.TestVersionInfo 2>&1 | tee -a $LOG
#onetest com.jogamp.common.util.TestVersionNumber 2>&1 | tee -a $LOG
-onetest com.jogamp.common.util.TestVersionSemantics 2>&1 | tee -a $LOG
+#onetest com.jogamp.common.util.TestVersionSemantics 2>&1 | tee -a $LOG
#onetest com.jogamp.common.util.TestIteratorIndexCORE 2>&1 | tee -a $LOG
#onetest com.jogamp.common.util.locks.TestRecursiveLock01 2>&1 | tee -a $LOG
#onetest com.jogamp.common.util.locks.TestRecursiveThreadGroupLock01 2>&1 | tee -a $LOG
@@ -133,7 +134,7 @@ onetest com.jogamp.common.util.TestVersionSemantics 2>&1 | tee -a $LOG
#onetest com.jogamp.common.nio.TestBuffersFloatDoubleConversion 2>&1 | tee -a $LOG
#onetest com.jogamp.common.nio.TestPointerBufferEndian 2>&1 | tee -a $LOG
#onetest com.jogamp.common.nio.TestStructAccessorEndian 2>&1 | tee -a $LOG
-#onetest com.jogamp.common.nio.TestByteBufferInputStream 2>&1 | tee -a $LOG
+onetest com.jogamp.common.nio.TestByteBufferInputStream 2>&1 | tee -a $LOG
#onetest com.jogamp.common.nio.TestByteBufferOutputStream 2>&1 | tee -a $LOG
#onetest com.jogamp.common.nio.TestByteBufferCopyStream 2>&1 | tee -a $LOG
#onetest com.jogamp.common.os.TestElfReader01 $* 2>&1 | tee -a $LOG
diff --git a/src/java/com/jogamp/common/nio/Buffers.java b/src/java/com/jogamp/common/nio/Buffers.java
index aae2be8..fb23627 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.Method;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -48,9 +49,14 @@ import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.common.util.ValueConv;
+import jogamp.common.Debug;
+
/**
* Utility methods allowing easy {@link java.nio.Buffer} manipulations.
*
@@ -60,6 +66,11 @@ import com.jogamp.common.util.ValueConv;
*/
public class Buffers {
+ static final boolean DEBUG;
+ static {
+ DEBUG = Debug.debug("Buffers");
+ }
+
public static final int SIZEOF_BYTE = 1;
public static final int SIZEOF_SHORT = 2;
public static final int SIZEOF_CHAR = 2;
@@ -1150,4 +1161,64 @@ public class Buffers {
return sb;
}
+ /**
+ * 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 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 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);
+ return Boolean.TRUE;
+ } catch(final Throwable t) {
+ if( DEBUG ) {
+ System.err.println("Caught "+t.getMessage());
+ t.printStackTrace();
+ }
+ return Boolean.FALSE;
+ } } } ).booleanValue() ) {
+ mbbCleaner = _mbbCleaner[0];
+ cClean = _cClean[0];
+ hasCleaner = null != mbbCleaner && null != cClean;
+ } else {
+ mbbCleaner = null;
+ cClean = null;
+ hasCleaner = false;
+ }
+ cleanerError = !hasCleaner;
+ }
+ /**
+ * 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() ) {
+ return false;
+ }
+ try {
+ cClean.invoke(mbbCleaner.invoke(b));
+ return true;
+ } catch(final Throwable t) {
+ cleanerError = true;
+ if( DEBUG ) {
+ System.err.println("Caught "+t.getMessage());
+ t.printStackTrace();
+ }
+ return false;
+ }
+ }
+ }
}
diff --git a/src/java/com/jogamp/common/nio/MappedByteBufferInputStream.java b/src/java/com/jogamp/common/nio/MappedByteBufferInputStream.java
index f8d5857..dbd3941 100644
--- a/src/java/com/jogamp/common/nio/MappedByteBufferInputStream.java
+++ b/src/java/com/jogamp/common/nio/MappedByteBufferInputStream.java
@@ -33,13 +33,10 @@ import java.io.OutputStream;
import java.io.PrintStream;
import java.io.RandomAccessFile;
import java.lang.ref.WeakReference;
-import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import jogamp.common.Debug;
@@ -163,10 +160,6 @@ public class MappedByteBufferInputStream extends InputStream {
private int refCount;
- private Method mbbCleaner;
- private Method cClean;
- private boolean cleanerInit;
- private boolean hasCleaner;
private CacheMode cmode;
private int sliceIdx;
@@ -229,8 +222,6 @@ public class MappedByteBufferInputStream extends InputStream {
notifyLengthChange( totalSize );
this.refCount = 1;
- this.cleanerInit = false;
- this.hasCleaner = false;
this.cmode = cmode;
this.sliceIdx = currSliceIdx;
@@ -630,58 +621,16 @@ public class MappedByteBufferInputStream extends InputStream {
}
}
private synchronized boolean cleanBuffer(final ByteBuffer mbb, final boolean syncBuffer) throws IOException {
- if( !cleanerInit ) {
- initCleaner(mbb);
- }
syncSlice(mbb, syncBuffer);
if( !mbb.isDirect() ) {
return false;
}
- boolean res = false;
- if ( hasCleaner ) {
- try {
- cClean.invoke(mbbCleaner.invoke(mbb));
- res = true;
- } catch(final Throwable t) {
- hasCleaner = false;
- if( DEBUG ) {
- System.err.println("Caught "+t.getMessage());
- t.printStackTrace();
- }
- }
- }
- if( !res && CacheMode.FLUSH_PRE_HARD == cmode ) {
+ if( !Buffers.Cleaner.clean(mbb) && CacheMode.FLUSH_PRE_HARD == cmode ) {
cmode = CacheMode.FLUSH_PRE_SOFT;
+ return false;
+ } else {
+ return true;
}
- return res;
- }
- private synchronized void initCleaner(final ByteBuffer bb) {
- final Method[] _mbbCleaner = { null };
- final Method[] _cClean = { null };
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- @Override
- public Object run() {
- try {
- _mbbCleaner[0] = bb.getClass().getMethod("cleaner");
- _mbbCleaner[0].setAccessible(true);
- _cClean[0] = Class.forName("sun.misc.Cleaner").getMethod("clean");
- _cClean[0].setAccessible(true);
- } catch(final Throwable t) {
- if( DEBUG ) {
- System.err.println("Caught "+t.getMessage());
- t.printStackTrace();
- }
- }
- return null;
- } } );
- mbbCleaner = _mbbCleaner[0];
- cClean = _cClean[0];
- final boolean res = null != mbbCleaner && null != cClean;
- if( DEBUG ) {
- System.err.println("initCleaner: Has cleaner: "+res+", mbbCleaner "+mbbCleaner+", cClean "+cClean);
- }
- hasCleaner = res;
- cleanerInit = true;
}
/**