Add workaround for possible classloader deadlock when trying to load JNI code (#10190)

Motivation:

netty_epoll_linuxsocket_JNI_OnLoad(...) may produce a deadlock with another thread that will load IOUtil in a static block. This seems to be a JDK bug which is not yet fixed. To workaround this we force IOUtil to be loaded from without java code before init the JNI code

Modifications:

Use Selector.open() as a workaround to load IOUtil

Result:

Fixes https://github.com/netty/netty/issues/10187
This commit is contained in:
Norman Maurer 2020-04-16 08:40:59 +02:00 committed by GitHub
parent fb5e2cd3aa
commit 6dad12defa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -25,6 +25,7 @@ import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.InternalLoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.nio.channels.Selector;
import java.util.Locale; import java.util.Locale;
import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.epollerr; import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.epollerr;
@ -49,6 +50,16 @@ public final class Native {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(Native.class); private static final InternalLogger logger = InternalLoggerFactory.getInstance(Native.class);
static { static {
Selector selector = null;
try {
// We call Selector.open() as this will under the hood cause IOUtil to be loaded.
// This is a workaround for a possible classloader deadlock that could happen otherwise:
//
// See https://github.com/netty/netty/issues/10187
selector = Selector.open();
} catch (IOException ignore) {
// Just ignore
}
try { try {
// First, try calling a side-effect free JNI method to see if the library was already // First, try calling a side-effect free JNI method to see if the library was already
// loaded by the application. // loaded by the application.
@ -56,6 +67,14 @@ public final class Native {
} catch (UnsatisfiedLinkError ignore) { } catch (UnsatisfiedLinkError ignore) {
// The library was not previously loaded, load it now. // The library was not previously loaded, load it now.
loadNativeLibrary(); loadNativeLibrary();
} finally {
try {
if (selector != null) {
selector.close();
}
} catch (IOException ignore) {
// Just ignore
}
} }
Socket.initialize(); Socket.initialize();
} }