diff --git a/common/src/main/java/io/netty/util/internal/CleanerJava9.java b/common/src/main/java/io/netty/util/internal/CleanerJava9.java index d111a7e54a..3a0c5854c3 100644 --- a/common/src/main/java/io/netty/util/internal/CleanerJava9.java +++ b/common/src/main/java/io/netty/util/internal/CleanerJava9.java @@ -21,6 +21,8 @@ import io.netty.util.internal.logging.InternalLoggerFactory; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.nio.ByteBuffer; +import java.security.AccessController; +import java.security.PrivilegedAction; /** * Provide a way to clean a ByteBuffer on Java9+. @@ -34,20 +36,26 @@ final class CleanerJava9 implements Cleaner { final Method method; final Throwable error; if (PlatformDependent0.hasUnsafe()) { - ByteBuffer buffer = ByteBuffer.allocateDirect(1); - Object maybeInvokeMethod; - try { - // See https://bugs.openjdk.java.net/browse/JDK-8171377 - Method m = PlatformDependent0.UNSAFE.getClass().getDeclaredMethod("invokeCleaner", ByteBuffer.class); - m.invoke(PlatformDependent0.UNSAFE, buffer); - maybeInvokeMethod = m; - } catch (NoSuchMethodException e) { - maybeInvokeMethod = e; - } catch (InvocationTargetException e) { - maybeInvokeMethod = e; - } catch (IllegalAccessException e) { - maybeInvokeMethod = e; - } + final ByteBuffer buffer = ByteBuffer.allocateDirect(1); + Object maybeInvokeMethod = AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Object run() { + try { + // See https://bugs.openjdk.java.net/browse/JDK-8171377 + Method m = PlatformDependent0.UNSAFE.getClass().getDeclaredMethod( + "invokeCleaner", ByteBuffer.class); + m.invoke(PlatformDependent0.UNSAFE, buffer); + return m; + } catch (NoSuchMethodException e) { + return e; + } catch (InvocationTargetException e) { + return e; + } catch (IllegalAccessException e) { + return e; + } + } + }); + if (maybeInvokeMethod instanceof Throwable) { method = null; error = (Throwable) maybeInvokeMethod; @@ -73,10 +81,35 @@ final class CleanerJava9 implements Cleaner { @Override public void freeDirectBuffer(ByteBuffer buffer) { - try { - INVOKE_CLEANER.invoke(PlatformDependent0.UNSAFE, buffer); - } catch (Throwable cause) { - PlatformDependent0.throwException(cause); + // Try to minimize overhead when there is no SecurityManager present. + // See https://bugs.openjdk.java.net/browse/JDK-8191053. + if (System.getSecurityManager() == null) { + try { + INVOKE_CLEANER.invoke(PlatformDependent0.UNSAFE, buffer); + } catch (Throwable cause) { + PlatformDependent0.throwException(cause); + } + } else { + freeDirectBufferPrivileged(buffer); + } + } + + private static void freeDirectBufferPrivileged(final ByteBuffer buffer) { + Exception error = AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Exception run() { + try { + INVOKE_CLEANER.invoke(PlatformDependent0.UNSAFE, buffer); + } catch (InvocationTargetException e) { + return e; + } catch (IllegalAccessException e) { + return e; + } + return null; + } + }); + if (error != null) { + PlatformDependent0.throwException(error); } } }