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-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org