CleanerJava9 should be able to do its job even with a SecurityManager installed. (#8204)

Motivation:

CleanerJava9 currently fails whever a SecurityManager is installed. We should make use of AccessController.doPrivileged(...) so the user can give it the correct rights.

Modifications:

Use doPrivileged(...) when needed.

Result:

Fixes https://github.com/netty/netty/issues/8201.
This commit is contained in:
Norman Maurer 2018-08-28 16:32:29 +02:00 committed by GitHub
parent 338ef96931
commit 8679c5ef43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 51 additions and 18 deletions

View File

@ -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<Object>() {
@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<Exception>() {
@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);
}
}
}