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
parent abdcf102da
commit 87db5803a9

View File

@ -25,6 +25,7 @@ import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import java.io.IOException;
import java.nio.channels.Selector;
import java.util.Locale;
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);
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 {
// First, try calling a side-effect free JNI method to see if the library was already
// loaded by the application.
@ -56,6 +67,14 @@ public final class Native {
} catch (UnsatisfiedLinkError ignore) {
// The library was not previously loaded, load it now.
loadNativeLibrary();
} finally {
try {
if (selector != null) {
selector.close();
}
} catch (IOException ignore) {
// Just ignore
}
}
Socket.initialize();
}