Repository: netty/netty
Issue: Allow Netty-epoll use from preloaded System library
Labels: feature

In the same vein as #5043, it would be really useful if there was some way to use Netty's epoll without it doing the library initialization itself.   The fix would be pretty much the same as here: 379ad2c02ed0c0ae9f94e4081e3f910ece6380b7

cc: @nmittler 


Issue comments:
This one may be a little trickier because the current implementation of [Native](https://github.com/netty/netty/blob/4.1/transport-native-epoll/src/main/java/io/netty/channel/epoll/Native.java#L60) assumes that it will throw if the library fails to load, rather than just printing out a debug message and proceeding

Is there some way of determining if the symbols have actually been loaded?

@normanmaurer thoughts?

@nmittler - is trying to call a native method and getting a [UnsatisfiedLinkError](https://docs.oracle.com/javase/7/docs/api/java/lang/UnsatisfiedLinkError.html) if no associated method has been linked sufficient for what you need?

@Scottmitch  That would probably  be good enough.  It looks like there are some side-effect free methods in Native.java like `offsetofEpollData()`.

@carl-mastrangelo - We can also add a side effect free method for this purpose (e.g. `initialize`, `isLinked`, etc...) to be more explicit.

@carl-mastrangelo @Scottmitch I think using `offsetofEpollData()` should be good enough for now.


Pull request review comments:
e -> ignore

done.

nit: fix indentation of these params

done


Patch that resolved the issue:
diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/Native.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/Native.java
index e4ba4ce2a70..d9244314fb2 100644
--- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/Native.java
+++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/Native.java
@@ -53,14 +53,16 @@
  */
 public final class Native {
     static {
-        String name = SystemPropertyUtil.get("os.name").toLowerCase(Locale.UK).trim();
-        if (!name.startsWith("linux")) {
-            throw new IllegalStateException("Only supported on Linux");
+        try {
+            // First, try calling a side-effect free JNI method to see if the library was already
+            // loaded by the application.
+            offsetofEpollData();
+        } catch (UnsatisfiedLinkError ignore) {
+            // The library was not previously loaded, load it now.
+            loadNativeLibrary();
         }
-        NativeLibraryLoader.load(SystemPropertyUtil.get("io.netty.packagePrefix", "").replace('.', '-') +
-                                 "netty-transport-native-epoll",
-                                 PlatformDependent.getClassLoader(Native.class));
     }
+
     // EventLoop operations and constants
     public static final int EPOLLIN = epollin();
     public static final int EPOLLOUT = epollout();
@@ -250,4 +252,13 @@ public static void setTcpMd5Sig(int fd, InetAddress address, byte[] key) throws
     private Native() {
         // utility
     }
+
+    private static void loadNativeLibrary() {
+        String name = SystemPropertyUtil.get("os.name").toLowerCase(Locale.UK).trim();
+        if (!name.startsWith("linux")) {
+            throw new IllegalStateException("Only supported on Linux");
+        }
+        NativeLibraryLoader.load(SystemPropertyUtil.get("io.netty.packagePrefix", "").replace('.', '-') +
+            "netty-transport-native-epoll", PlatformDependent.getClassLoader(Native.class));
+    }
 }


Test patch: