diff options
Diffstat (limited to 'src/java/com')
-rw-r--r-- | src/java/com/jogamp/common/nio/Buffers.java | 71 | ||||
-rw-r--r-- | src/java/com/jogamp/common/nio/MappedByteBufferInputStream.java | 59 |
2 files changed, 75 insertions, 55 deletions
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; } /** |