* BufferUtils.destroyDirectBuffer() will only look up methods once

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9207 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
Sha..rd 13 years ago
parent 68da72cf66
commit f3528f8d6e
  1. 63
      engine/src/core/com/jme3/util/BufferUtils.java

@ -42,6 +42,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -1144,6 +1145,47 @@ public final class BufferUtils {
} }
} }
private static final AtomicBoolean loadedMethods = new AtomicBoolean(false);
private static Method cleanerMethod = null;
private static Method cleanMethod = null;
private static Method viewedBufferMethod = null;
private static Method freeMethod = null;
private static Method loadMethod(String className, String methodName){
try {
Method method = Class.forName(className).getMethod(methodName);
method.setAccessible(true);
return method;
} catch (NoSuchMethodException ex) {
return null; // the method was not found
} catch (SecurityException ex) {
return null; // setAccessible not allowed by security policy
} catch (ClassNotFoundException ex) {
return null; // the direct buffer implementation was not found
}
}
private static void loadCleanerMethods() {
// If its already true, exit, if not, set it to true.
if (loadedMethods.getAndSet(true)) {
return;
}
// This could potentially be called many times if used from multiple
// threads
synchronized (loadedMethods) {
// Oracle JRE / OpenJDK
cleanerMethod = loadMethod("sun.nio.ch.DirectBuffer", "cleaner");
cleanMethod = loadMethod("sun.misc.Cleaner", "clean");
viewedBufferMethod = loadMethod("sun.nio.ch.DirectBuffer", "viewedBuffer");
// Apache Harmony
freeMethod = loadMethod("java.nio.DirectByteBuffer", "free");
// GUN Classpath (not likely)
//finalizeMethod = loadMethod("java.nio.DirectByteBufferImpl", "finalize");
}
}
/** /**
* Direct buffers are garbage collected by using a phantom reference and a * Direct buffers are garbage collected by using a phantom reference and a
* reference queue. Every once a while, the JVM checks the reference queue and * reference queue. Every once a while, the JVM checks the reference queue and
@ -1157,40 +1199,37 @@ public final class BufferUtils {
* *
*/ */
public static void destroyDirectBuffer(Buffer toBeDestroyed) { public static void destroyDirectBuffer(Buffer toBeDestroyed) {
if (!toBeDestroyed.isDirect()) { if (!toBeDestroyed.isDirect()) {
return; return;
} }
loadCleanerMethods();
try { try {
Method cleanerMethod = toBeDestroyed.getClass().getMethod("cleaner"); if (freeMethod != null) {
cleanerMethod.setAccessible(true); freeMethod.invoke(toBeDestroyed);
} else {
Object cleaner = cleanerMethod.invoke(toBeDestroyed); Object cleaner = cleanerMethod.invoke(toBeDestroyed);
if (cleaner != null) { if (cleaner != null) {
Method cleanMethod = cleaner.getClass().getMethod("clean");
cleanMethod.setAccessible(true);
cleanMethod.invoke(cleaner); cleanMethod.invoke(cleaner);
} else { } else {
// Try the alternate approach of getting the viewed buffer // Try the alternate approach of getting the viewed buffer first
Method viewedBufferMethod = toBeDestroyed.getClass().getMethod("viewedBuffer");
viewedBufferMethod.setAccessible(true);
Object viewedBuffer = viewedBufferMethod.invoke(toBeDestroyed); Object viewedBuffer = viewedBufferMethod.invoke(toBeDestroyed);
if (viewedBuffer != null) { if (viewedBuffer != null) {
destroyDirectBuffer( (Buffer)viewedBuffer ); destroyDirectBuffer((Buffer) viewedBuffer);
} else { } else {
Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "Buffer cannot be destroyed: {0}", toBeDestroyed); Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "Buffer cannot be destroyed: {0}", toBeDestroyed);
} }
} }
}
} catch (IllegalAccessException ex) { } catch (IllegalAccessException ex) {
Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "{0}", ex); Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "{0}", ex);
} catch (IllegalArgumentException ex) { } catch (IllegalArgumentException ex) {
Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "{0}", ex); Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "{0}", ex);
} catch (InvocationTargetException ex) { } catch (InvocationTargetException ex) {
Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "{0}", ex); Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "{0}", ex);
} catch (NoSuchMethodException ex) {
Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "{0}", ex);
} catch (SecurityException ex) { } catch (SecurityException ex) {
Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "{0}", ex); Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "{0}", ex);
} }
} }
} }

Loading…
Cancel
Save