You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2017/01/20 13:09:56 UTC

svn commit: r1779622 - in /tomcat/trunk: java/org/apache/tomcat/util/buf/ByteBufferUtils.java webapps/docs/changelog.xml

Author: remm
Date: Fri Jan 20 13:09:56 2017
New Revision: 1779622

URL: http://svn.apache.org/viewvc?rev=1779622&view=rev
Log:
Restore Java 9 direct byte buffer cleanup code, for now. The last way to access it is through the private Unsafe singleton, which will likely stop working at some point :(

Modified:
    tomcat/trunk/java/org/apache/tomcat/util/buf/ByteBufferUtils.java
    tomcat/trunk/webapps/docs/changelog.xml

Modified: tomcat/trunk/java/org/apache/tomcat/util/buf/ByteBufferUtils.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/buf/ByteBufferUtils.java?rev=1779622&r1=1779621&r2=1779622&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/buf/ByteBufferUtils.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/buf/ByteBufferUtils.java Fri Jan 20 13:09:56 2017
@@ -16,6 +16,7 @@
  */
 package org.apache.tomcat.util.buf;
 
+import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.nio.ByteBuffer;
@@ -31,38 +32,57 @@ public class ByteBufferUtils {
     private static final StringManager sm = StringManager.getManager(ByteBufferUtils.class);
     private static final Log log = LogFactory.getLog(ByteBufferUtils.class);
 
+    private static final Object unsafe;
     private static final Method cleanerMethod;
     private static final Method cleanMethod;
+    private static final Method invokeCleanerMethod;
 
     static {
         ByteBuffer tempBuffer = ByteBuffer.allocateDirect(0);
         Method cleanerMethodLocal = null;
         Method cleanMethodLocal = null;
-        try {
-            cleanerMethodLocal = tempBuffer.getClass().getMethod("cleaner");
-            cleanerMethodLocal.setAccessible(true);
-            Object cleanerObject = cleanerMethodLocal.invoke(tempBuffer);
-            if (cleanerObject instanceof Runnable) {
-                cleanMethodLocal = Runnable.class.getMethod("run");
-            } else {
-                cleanMethodLocal = cleanerObject.getClass().getMethod("clean");
+        Object unsafeLocal = null;
+        Method invokeCleanerMethodLocal = null;
+        if (JreCompat.isJre9Available()) {
+            try {
+                Class<?> clazz = Class.forName("sun.misc.Unsafe");
+                Field theUnsafe = clazz.getDeclaredField("theUnsafe");
+                theUnsafe.setAccessible(true);
+                unsafeLocal = theUnsafe.get(null);
+                invokeCleanerMethodLocal = clazz.getMethod("invokeCleaner", ByteBuffer.class);
+                invokeCleanerMethodLocal.invoke(unsafeLocal, tempBuffer);
+            } catch (IllegalAccessException | IllegalArgumentException
+                    | InvocationTargetException | NoSuchMethodException | SecurityException
+                    | ClassNotFoundException | NoSuchFieldException e) {
+                log.warn(sm.getString("byteBufferUtils.cleaner"), e);
+                unsafeLocal = null;
+                invokeCleanerMethodLocal = null;
             }
-            cleanMethodLocal.invoke(cleanerObject);
-        } catch (Throwable t) {
-            JreCompat jreCompat = JreCompat.getInstance();
-            if (jreCompat.isInstanceOfInaccessibleObjectException(t)) {
-                // Must be running on Java 9 without the necessary command line
-                // options.
-                log.warn(sm.getString("byteBufferUtils.addExportsCleaner"));
-            } else {
-                ExceptionUtils.handleThrowable(t);
+        } else {
+            try {
+                cleanerMethodLocal = tempBuffer.getClass().getMethod("cleaner");
+                cleanerMethodLocal.setAccessible(true);
+                Object cleanerObject = cleanerMethodLocal.invoke(tempBuffer);
+                cleanMethodLocal = cleanerObject.getClass().getMethod("clean");
+                cleanMethodLocal.invoke(cleanerObject);
+            } catch (Throwable t) {
+                JreCompat jreCompat = JreCompat.getInstance();
+                if (jreCompat.isInstanceOfInaccessibleObjectException(t)) {
+                    // Must be running on Java 9 without the necessary command line
+                    // options.
+                    log.warn(sm.getString("byteBufferUtils.addExportsCleaner"));
+                } else {
+                    ExceptionUtils.handleThrowable(t);
+                }
+                log.warn(sm.getString("byteBufferUtils.cleaner"), t);
+                cleanerMethodLocal = null;
+                cleanMethodLocal = null;
             }
-            log.warn(sm.getString("byteBufferUtils.cleaner"), t);
-            cleanerMethodLocal = null;
-            cleanMethodLocal = null;
         }
         cleanerMethod = cleanerMethodLocal;
         cleanMethod = cleanMethodLocal;
+        unsafe = unsafeLocal;
+        invokeCleanerMethod = invokeCleanerMethodLocal;
     }
 
     private ByteBufferUtils() {
@@ -114,6 +134,14 @@ public class ByteBufferUtils {
                     | InvocationTargetException | SecurityException e) {
                 // Ignore
             }
+        } else if (invokeCleanerMethod != null) {
+            try {
+                invokeCleanerMethod.invoke(unsafe, buf);
+            } catch (IllegalAccessException | IllegalArgumentException
+                    | InvocationTargetException | SecurityException e) {
+                // Ignore
+                e.printStackTrace();
+            }
         }
     }
 

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1779622&r1=1779621&r2=1779622&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Fri Jan 20 13:09:56 2017
@@ -60,6 +60,9 @@
         connectors when using the JSSE implementation for TLS when running on
         Java 9. (markt)
       </add>
+      <fix>
+        Restore Java 9 direct byte buffer compatibility. (remm)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Cluster">



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org