From 7fb62a93b8000c73ad2c40fc22bd02f289f1623a Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Fri, 18 Dec 2020 10:37:49 +0100 Subject: [PATCH] Ensure we only register native methods once (#10876) Motivation: We need to ensure we only register native methods once as otherwise we may end up in an "invalid" state. The problem here was that before it was basically the responsibility the user of transport-native-unix-common to register the methods. This is error prone as there may be multiple users of these on the classpath at the same time. Modifications: - Provide a way to init native lib without register the native methods of the provided classes. This is needed to be able to re-use functionality which is exposed to our internal native code - Use flatten plugin to correctly resolve classifier and so have the correct dependency - Call Unix.* method to ensure we register the methods correctly once - Include native lib as well in the native jars of unix-common Result: Be able to have multiple artifacts of the classpath that depends on the unix-common. Related to https://github.com/netty/netty-incubator-transport-io_uring/issues/15 --- all/pom.xml | 76 ++++- pom.xml | 27 ++ resolver-dns-native-macos/pom.xml | 33 +- .../MacOSDnsServerAddressStreamProvider.java | 2 + testsuite-osgi/pom.xml | 1 + transport-native-epoll/pom.xml | 37 +- .../java/io/netty/channel/epoll/Epoll.java | 2 + transport-native-kqueue/pom.xml | 44 +-- .../java/io/netty/channel/kqueue/KQueue.java | 2 + transport-native-unix-common/Makefile | 3 +- transport-native-unix-common/pom.xml | 319 ++++-------------- .../c/internal/netty_unix_buffer_internal.h | 25 ++ .../c/internal/netty_unix_errors_internal.h | 25 ++ .../netty_unix_filedescriptor_internal.h | 25 ++ .../c/internal/netty_unix_limits_internal.h | 25 ++ .../c/internal/netty_unix_socket_internal.h | 25 ++ .../src/main/c/netty_unix_buffer.c | 40 ++- .../src/main/c/netty_unix_errors.c | 41 ++- .../src/main/c/netty_unix_filedescriptor.c | 30 +- .../src/main/c/netty_unix_limits.c | 39 ++- .../src/main/c/netty_unix_native.c | 124 +++++++ .../src/main/c/netty_unix_socket.c | 54 ++- .../io/netty/channel/unix/FileDescriptor.java | 1 + .../java/io/netty/channel/unix/IovArray.java | 4 +- .../main/java/io/netty/channel/unix/Unix.java | 128 +++++++ 25 files changed, 791 insertions(+), 341 deletions(-) create mode 100644 transport-native-unix-common/src/main/c/internal/netty_unix_buffer_internal.h create mode 100644 transport-native-unix-common/src/main/c/internal/netty_unix_errors_internal.h create mode 100644 transport-native-unix-common/src/main/c/internal/netty_unix_filedescriptor_internal.h create mode 100644 transport-native-unix-common/src/main/c/internal/netty_unix_limits_internal.h create mode 100644 transport-native-unix-common/src/main/c/internal/netty_unix_socket_internal.h create mode 100644 transport-native-unix-common/src/main/c/netty_unix_native.c create mode 100644 transport-native-unix-common/src/main/java/io/netty/channel/unix/Unix.java diff --git a/all/pom.xml b/all/pom.xml index d9078e0821d1..572a38341610 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -61,6 +61,27 @@ + + ${project.groupId} + netty-transport-native-unix-common + linux-x86_64 + compile + true + + + ${project.groupId} + netty-transport-native-unix-common + linux-aarch_64 + compile + true + + + ${project.groupId} + netty-transport-native-unix-common + osx-x86_64 + compile + true + ${project.groupId} netty-transport-native-epoll @@ -97,6 +118,27 @@ + + ${project.groupId} + netty-transport-native-unix-common + linux-x86_64 + compile + true + + + ${project.groupId} + netty-transport-native-unix-common + linux-aarch_64 + compile + true + + + ${project.groupId} + netty-transport-native-unix-common + osx-x86_64 + compile + true + ${project.groupId} netty-transport-native-epoll @@ -128,7 +170,7 @@ - @@ -140,6 +182,14 @@ + + ${project.groupId} + netty-transport-native-unix-common + ${project.version} + ${jni.classifier} + compile + true + ${project.groupId} netty-transport-native-epoll @@ -175,6 +225,14 @@ + + ${project.groupId} + netty-transport-native-unix-common + ${project.version} + ${jni.classifier} + compile + true + ${project.groupId} netty-transport-native-kqueue @@ -209,6 +267,14 @@ + + ${project.groupId} + netty-transport-native-unix-common + ${project.version} + ${jni.classifier} + compile + true + ${project.groupId} netty-transport-native-kqueue @@ -236,6 +302,14 @@ + + ${project.groupId} + netty-transport-native-unix-common + ${project.version} + ${jni.classifier} + compile + true + ${project.groupId} netty-transport-native-kqueue diff --git a/pom.xml b/pom.xml index 2519b36c4915..dd76cc2d42b1 100644 --- a/pom.xml +++ b/pom.xml @@ -1309,6 +1309,33 @@ + + org.codehaus.mojo + flatten-maven-plugin + 1.2.2 + + + + flatten + process-resources + + flatten + + + + + flatten.clean + clean + + clean + + + + + oss + ${project.build.directory} + + maven-surefire-plugin diff --git a/resolver-dns-native-macos/pom.xml b/resolver-dns-native-macos/pom.xml index 9141121eef92..96ce6dc72bb7 100644 --- a/resolver-dns-native-macos/pom.xml +++ b/resolver-dns-native-macos/pom.xml @@ -124,11 +124,23 @@ netty-transport-native-unix-common ${project.version} ${jni.classifier} - - true + + + + + + non-native + + true + + + + io.netty + netty-transport-native-unix-common + ${project.version} @@ -156,15 +168,16 @@ netty-resolver-dns ${project.version} - - io.netty - netty-transport-native-unix-common - ${project.version} - + + + org.codehaus.mojo + flatten-maven-plugin + + maven-jar-plugin diff --git a/resolver-dns-native-macos/src/main/java/io/netty/resolver/dns/macos/MacOSDnsServerAddressStreamProvider.java b/resolver-dns-native-macos/src/main/java/io/netty/resolver/dns/macos/MacOSDnsServerAddressStreamProvider.java index 71cbbcb0b7a0..03b826e02cec 100644 --- a/resolver-dns-native-macos/src/main/java/io/netty/resolver/dns/macos/MacOSDnsServerAddressStreamProvider.java +++ b/resolver-dns-native-macos/src/main/java/io/netty/resolver/dns/macos/MacOSDnsServerAddressStreamProvider.java @@ -15,6 +15,7 @@ */ package io.netty.resolver.dns.macos; +import io.netty.channel.unix.Unix; import io.netty.resolver.dns.DnsServerAddressStream; import io.netty.resolver.dns.DnsServerAddressStreamProvider; import io.netty.resolver.dns.DnsServerAddressStreamProviders; @@ -53,6 +54,7 @@ public final class MacOSDnsServerAddressStreamProvider implements DnsServerAddre static { Throwable cause = null; try { + Unix.ensureAvailability(); loadNativeLibrary(); } catch (Throwable error) { cause = error; diff --git a/testsuite-osgi/pom.xml b/testsuite-osgi/pom.xml index d0edce6cb8c6..45da8c3773f9 100644 --- a/testsuite-osgi/pom.xml +++ b/testsuite-osgi/pom.xml @@ -241,6 +241,7 @@ test + ${line.separator} diff --git a/transport-native-epoll/pom.xml b/transport-native-epoll/pom.xml index 24b7c807fed3..82d09b1b227c 100644 --- a/transport-native-epoll/pom.xml +++ b/transport-native-epoll/pom.xml @@ -202,11 +202,6 @@ netty-transport-native-unix-common ${project.version} ${jni.classifier} - - true @@ -351,11 +346,23 @@ netty-transport-native-unix-common ${project.version} ${jni.classifier} - - true + + + + + + non-native + + true + + + + io.netty + netty-transport-native-unix-common + ${project.version} @@ -377,11 +384,6 @@ netty-transport ${project.version} - - io.netty - netty-transport-native-unix-common - ${project.version} - io.netty netty-testsuite @@ -405,6 +407,11 @@ + + + org.codehaus.mojo + flatten-maven-plugin + org.codehaus.mojo diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/Epoll.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/Epoll.java index 44ba7f6779eb..92a4a4b04f81 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/Epoll.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/Epoll.java @@ -16,6 +16,7 @@ package io.netty.channel.epoll; import io.netty.channel.unix.FileDescriptor; +import io.netty.channel.unix.Unix; import io.netty.util.internal.SystemPropertyUtil; /** @@ -36,6 +37,7 @@ public final class Epoll { FileDescriptor epollFd = null; FileDescriptor eventFd = null; try { + Unix.ensureAvailability(); epollFd = Native.newEpollCreate(); eventFd = Native.newEventFd(); } catch (Throwable t) { diff --git a/transport-native-kqueue/pom.xml b/transport-native-kqueue/pom.xml index 032a1c5b4493..29fa83778957 100644 --- a/transport-native-kqueue/pom.xml +++ b/transport-native-kqueue/pom.xml @@ -62,7 +62,6 @@ - org.fusesource.hawtjni maven-hawtjni-plugin @@ -129,11 +128,6 @@ netty-transport-native-unix-common ${project.version} ${jni.classifier} - - true @@ -235,11 +229,6 @@ netty-transport-native-unix-common ${project.version} ${jni.classifier} - - true @@ -341,11 +330,23 @@ netty-transport-native-unix-common ${project.version} ${jni.classifier} - - true + + + + + + non-native + + true + + + + io.netty + netty-transport-native-unix-common + ${project.version} @@ -381,11 +382,6 @@ netty-transport ${project.version} - - io.netty - netty-transport-native-unix-common - ${project.version} - io.netty netty-testsuite @@ -408,6 +404,12 @@ + + + org.codehaus.mojo + flatten-maven-plugin + + org.codehaus.mojo diff --git a/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/KQueue.java b/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/KQueue.java index 83cb496251cf..2012b7510a73 100644 --- a/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/KQueue.java +++ b/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/KQueue.java @@ -16,6 +16,7 @@ package io.netty.channel.kqueue; import io.netty.channel.unix.FileDescriptor; +import io.netty.channel.unix.Unix; import io.netty.util.internal.SystemPropertyUtil; import io.netty.util.internal.UnstableApi; @@ -34,6 +35,7 @@ public final class KQueue { } else { FileDescriptor kqueueFd = null; try { + Unix.ensureAvailability(); kqueueFd = Native.newKQueue(); } catch (Throwable t) { cause = t; diff --git a/transport-native-unix-common/Makefile b/transport-native-unix-common/Makefile index 8f9eade97dcb..3d358a33ed7f 100644 --- a/transport-native-unix-common/Makefile +++ b/transport-native-unix-common/Makefile @@ -23,12 +23,13 @@ # LIB_NAME - the name of the native library SRC_DIR = src/main/c +SRC_INTERNAL_DIR = src/main/c/internal UTIL_SRC_DIR = target/netty-jni-util/src/c JNI_INCLUDE_DIR = $(JAVA_HOME)/include JNI_INCLUDES = -I$(JNI_INCLUDE_DIR) -I$(JNI_INCLUDE_DIR)/$(JNI_PLATFORM) LIB = $(LIB_DIR)/$(LIB_NAME).a -CFLAGS += $(JNI_INCLUDES) -I$(UTIL_SRC_DIR) +CFLAGS += $(JNI_INCLUDES) -I$(UTIL_SRC_DIR) -I$(SRC_INTERNAL_DIR) SRCS = $(wildcard $(SRC_DIR)/*.c) UTIL_SRCS = $(wildcard $(UTIL_SRC_DIR)/*.c) diff --git a/transport-native-unix-common/pom.xml b/transport-native-unix-common/pom.xml index 5755d5d2e8f4..7cfe7650b779 100644 --- a/transport-native-unix-common/pom.xml +++ b/transport-native-unix-common/pom.xml @@ -44,6 +44,11 @@ ${project.build.directory}/native-lib-only ${project.build.directory}/${project.build.finalName}.jar ${project.build.directory}/${project.build.finalName}-${jni.classifier}.jar + ${project.build.directory}/generated-sources + -O3 -Werror -Wno-attributes -fPIC -fno-omit-frame-pointer -Wunused-variable -fvisibility=hidden -I${project.basedir}/src/main/c + -Wl,--no-as-needed -lrt + ${os.detected.arch} + false @@ -102,73 +107,10 @@ + true clang darwin - - - - maven-antrun-plugin - - - - native-jar - package - - run - - - - - - - - - - - - - - - - - - - - - - - - - - build-native-lib - generate-sources - - run - - - - - - - - - - - - - - - - - - - - - - linux @@ -180,136 +122,17 @@ linux - - - - maven-antrun-plugin - - - - native-jar - package - - run - - - - - - - - - - - - - - - - - - - - - - - - - - build-native-lib - generate-sources - - run - - - - - - - - - - - - - - - - - - - - linux-aarch64 + aarch_64 ${os.detected.name}-aarch_64 linux aarch64-linux-gnu-gcc aarch64-linux-gnu-ar - - - - maven-antrun-plugin - - - - native-jar - package - - run - - - - - - - - - - - - - - - - - - - - - - - - - - build-native-lib - generate-sources - - run - - - - - - - - - - - - - - - - - - - - freebsd @@ -324,6 +147,29 @@ gmake freebsd + + + openbsd + + + unix + openbsd + + + + clang + gmake + openbsd + + + + + build.native + + + !windows + + @@ -347,10 +193,11 @@ - + + - + @@ -373,89 +220,69 @@ - - + + + + - - - - - - - openbsd - - - unix - openbsd - - - - clang - gmake - openbsd - - - - - maven-antrun-plugin - - + - native-jar - package + copy-src + generate-sources run - - - - - - + + + + - - - - - - - + + + - - - + + + + org.fusesource.hawtjni + maven-hawtjni-plugin + build-native-lib - generate-sources - - run - - - - - - - - - - - - - + netty_transport_native_unix_${os.detected.name}_${nativeLibArch} + ${generatedSourcesDir} + ${project.build.outputDirectory} + + . + true + true + + MACOSX_DEPLOYMENT_TARGET=10.2 + CFLAGS=${cflags} + + + generate + build + + diff --git a/transport-native-unix-common/src/main/c/internal/netty_unix_buffer_internal.h b/transport-native-unix-common/src/main/c/internal/netty_unix_buffer_internal.h new file mode 100644 index 000000000000..720dcce67793 --- /dev/null +++ b/transport-native-unix-common/src/main/c/internal/netty_unix_buffer_internal.h @@ -0,0 +1,25 @@ +/* + * Copyright 2020 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +#ifndef NETTY_UNIX_BUFFER_INTERNAL_H_ +#define NETTY_UNIX_BUFFER_INTERNAL_H_ + +#include + +// JNI initialization hooks. Users of this file are responsible for calling these in the JNI_OnLoad and JNI_OnUnload methods. +jint netty_unix_buffer_internal_JNI_OnLoad(JNIEnv* env, const char* packagePrefix); +void netty_unix_buffer_internal_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix); + +#endif /* NETTY_UNIX_BUFFER_INTERNAL_H_ */ diff --git a/transport-native-unix-common/src/main/c/internal/netty_unix_errors_internal.h b/transport-native-unix-common/src/main/c/internal/netty_unix_errors_internal.h new file mode 100644 index 000000000000..07d82df48f59 --- /dev/null +++ b/transport-native-unix-common/src/main/c/internal/netty_unix_errors_internal.h @@ -0,0 +1,25 @@ +/* + * Copyright 2020 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +#ifndef NETTY_UNIX_ERRORS_INTERNAL_H_ +#define NETTY_UNIX_ERRORS_INTERNAL_H_ + +#include + +// JNI initialization hooks. Users of this file are responsible for calling these in the JNI_OnLoad and JNI_OnUnload methods. +jint netty_unix_errors_internal_JNI_OnLoad(JNIEnv* env, const char* packagePrefix); +void netty_unix_errors_internal_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix); + +#endif /* NETTY_UNIX_ERRORS_INTERNAL_H_ */ diff --git a/transport-native-unix-common/src/main/c/internal/netty_unix_filedescriptor_internal.h b/transport-native-unix-common/src/main/c/internal/netty_unix_filedescriptor_internal.h new file mode 100644 index 000000000000..be51b87f5a93 --- /dev/null +++ b/transport-native-unix-common/src/main/c/internal/netty_unix_filedescriptor_internal.h @@ -0,0 +1,25 @@ +/* + * Copyright 2020 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +#ifndef NETTY_UNIX_FILEDESCRIPTOR_INTERNAL_H_ +#define NETTY_UNIX_FILEDESCRIPTOR_INTERNAL_H_ + +#include + +// JNI initialization hooks. Users of this file are responsible for calling these in the JNI_OnLoad and JNI_OnUnload methods. +jint netty_unix_filedescriptor_internal_JNI_OnLoad(JNIEnv* env, const char* packagePrefix); +void netty_unix_filedescriptor_internal_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix); + +#endif /* NETTY_UNIX_FILEDESCRIPTOR_INTERNAL_H_ */ diff --git a/transport-native-unix-common/src/main/c/internal/netty_unix_limits_internal.h b/transport-native-unix-common/src/main/c/internal/netty_unix_limits_internal.h new file mode 100644 index 000000000000..23329c72d1f8 --- /dev/null +++ b/transport-native-unix-common/src/main/c/internal/netty_unix_limits_internal.h @@ -0,0 +1,25 @@ +/* + * Copyright 2020 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +#ifndef NETTY_UNIX_LIMITS_INTERNAL_H_ +#define NETTY_UNIX_LIMITS_INTERNAL_H_ + +#include + +// JNI initialization hooks. Users of this file are responsible for calling these in the JNI_OnLoad and JNI_OnUnload methods. +jint netty_unix_limits_internal_JNI_OnLoad(JNIEnv* env, const char* packagePrefix); +void netty_unix_limits_internal_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix); + +#endif /* NETTY_UNIX_LIMITS_INTERNAL_H_ */ diff --git a/transport-native-unix-common/src/main/c/internal/netty_unix_socket_internal.h b/transport-native-unix-common/src/main/c/internal/netty_unix_socket_internal.h new file mode 100644 index 000000000000..227a9b0301fc --- /dev/null +++ b/transport-native-unix-common/src/main/c/internal/netty_unix_socket_internal.h @@ -0,0 +1,25 @@ +/* + * Copyright 2020 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +#ifndef NETTY_UNIX_SOCKET_INTERNAL_H_ +#define NETTY_UNIX_SOCKET_INTERNAL_H_ + +#include + +// JNI initialization hooks. Users of this file are responsible for calling these in the JNI_OnLoad and JNI_OnUnload methods. +jint netty_unix_socket_internal_JNI_OnLoad(JNIEnv* env, const char* packagePrefix); +void netty_unix_socket_internal_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix); + +#endif /* NETTY_UNIX_SOCKET_INTERNAL_H_ */ diff --git a/transport-native-unix-common/src/main/c/netty_unix_buffer.c b/transport-native-unix-common/src/main/c/netty_unix_buffer.c index db922ab3966a..517cabd5c2c6 100644 --- a/transport-native-unix-common/src/main/c/netty_unix_buffer.c +++ b/transport-native-unix-common/src/main/c/netty_unix_buffer.c @@ -17,6 +17,7 @@ #include "netty_unix_util.h" #include "netty_unix_buffer.h" #include "netty_jni_util.h" +#include "internal/netty_unix_buffer_internal.h" #define BUFFER_CLASSNAME "io/netty/channel/unix/Buffer" @@ -39,19 +40,40 @@ static const JNINativeMethod statically_referenced_fixed_method_table[] = { static const jint statically_referenced_fixed_method_table_size = sizeof(statically_referenced_fixed_method_table) / sizeof(statically_referenced_fixed_method_table[0]); // JNI Method Registration Table End -jint netty_unix_buffer_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { - // We must register the statically referenced methods first! - if (netty_jni_util_register_natives(env, - packagePrefix, - BUFFER_CLASSNAME, - statically_referenced_fixed_method_table, - statically_referenced_fixed_method_table_size) != 0) { - return JNI_ERR; +static jint netty_unix_buffer_JNI_OnLoad0(JNIEnv* env, const char* packagePrefix, int registerNative) { + if (registerNative) { + // We must register the statically referenced methods first! + if (netty_jni_util_register_natives(env, + packagePrefix, + BUFFER_CLASSNAME, + statically_referenced_fixed_method_table, + statically_referenced_fixed_method_table_size) != 0) { + return JNI_ERR; + } } return NETTY_JNI_UTIL_JNI_VERSION; } +static void netty_unix_buffer_JNI_OnUnLoad0(JNIEnv* env, const char* packagePrefix, int unregisterNative) { + if (unregisterNative) { + netty_jni_util_unregister_natives(env, packagePrefix, BUFFER_CLASSNAME); + } +} + +jint netty_unix_buffer_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { + return netty_unix_buffer_JNI_OnLoad0(env, packagePrefix, 0); +} + void netty_unix_buffer_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { - netty_jni_util_unregister_natives(env, packagePrefix, BUFFER_CLASSNAME); + netty_unix_buffer_JNI_OnUnLoad0(env, packagePrefix, 0); +} + +jint netty_unix_buffer_internal_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { + return netty_unix_buffer_JNI_OnLoad0(env, packagePrefix, 1); } + +void netty_unix_buffer_internal_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { + netty_unix_buffer_JNI_OnUnLoad0(env, packagePrefix, 1); +} + diff --git a/transport-native-unix-common/src/main/c/netty_unix_errors.c b/transport-native-unix-common/src/main/c/netty_unix_errors.c index 8ecc14760d90..b7627b92179c 100644 --- a/transport-native-unix-common/src/main/c/netty_unix_errors.c +++ b/transport-native-unix-common/src/main/c/netty_unix_errors.c @@ -21,6 +21,7 @@ #include "netty_unix_jni.h" #include "netty_unix_util.h" #include "netty_jni_util.h" +#include "internal/netty_unix_errors_internal.h" #define ERRORS_CLASSNAME "io/netty/channel/unix/ErrorsStaticallyReferencedJniMethods" @@ -212,15 +213,17 @@ static const JNINativeMethod statically_referenced_fixed_method_table[] = { static const jint statically_referenced_fixed_method_table_size = sizeof(statically_referenced_fixed_method_table) / sizeof(statically_referenced_fixed_method_table[0]); // JNI Method Registration Table End -jint netty_unix_errors_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { +static jint netty_unix_errors_JNI_OnLoad0(JNIEnv* env, const char* packagePrefix, int registerNative) { char* nettyClassName = NULL; - // We must register the statically referenced methods first! - if (netty_jni_util_register_natives(env, - packagePrefix, - ERRORS_CLASSNAME, - statically_referenced_fixed_method_table, - statically_referenced_fixed_method_table_size) != 0) { - return JNI_ERR; + if (registerNative) { + // We must register the statically referenced methods first! + if (netty_jni_util_register_natives(env, + packagePrefix, + ERRORS_CLASSNAME, + statically_referenced_fixed_method_table, + statically_referenced_fixed_method_table_size) != 0) { + return JNI_ERR; + } } NETTY_JNI_UTIL_LOAD_CLASS(env, oomErrorClass, "java/lang/OutOfMemoryError", error); @@ -244,7 +247,7 @@ jint netty_unix_errors_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { return JNI_ERR; } -void netty_unix_errors_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { +static void netty_unix_errors_JNI_OnUnLoad0(JNIEnv* env, const char* packagePrefix, int unregisterNative) { // delete global references so the GC can collect them NETTY_JNI_UTIL_UNLOAD_CLASS(env, oomErrorClass); NETTY_JNI_UTIL_UNLOAD_CLASS(env, runtimeExceptionClass); @@ -253,5 +256,23 @@ void netty_unix_errors_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { NETTY_JNI_UTIL_UNLOAD_CLASS(env, portUnreachableExceptionClass); NETTY_JNI_UTIL_UNLOAD_CLASS(env, closedChannelExceptionClass); - netty_jni_util_unregister_natives(env, packagePrefix, ERRORS_CLASSNAME); + if (unregisterNative) { + netty_jni_util_unregister_natives(env, packagePrefix, ERRORS_CLASSNAME); + } +} + +jint netty_unix_errors_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { + return netty_unix_errors_JNI_OnLoad0(env, packagePrefix, 0); +} + +void netty_unix_errors_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { + netty_unix_errors_JNI_OnUnLoad0(env, packagePrefix, 0); +} + +jint netty_unix_errors_internal_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { + return netty_unix_errors_JNI_OnLoad0(env, packagePrefix, 1); +} + +void netty_unix_errors_internal_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { + netty_unix_errors_JNI_OnUnLoad0(env, packagePrefix, 1); } diff --git a/transport-native-unix-common/src/main/c/netty_unix_filedescriptor.c b/transport-native-unix-common/src/main/c/netty_unix_filedescriptor.c index d226b7636e21..31bb25cc04ce 100644 --- a/transport-native-unix-common/src/main/c/netty_unix_filedescriptor.c +++ b/transport-native-unix-common/src/main/c/netty_unix_filedescriptor.c @@ -27,6 +27,8 @@ #include "netty_unix_util.h" #include "netty_jni_util.h" +#include "internal/netty_unix_filedescriptor_internal.h" + #define FILEDESCRIPTOR_CLASSNAME "io/netty/channel/unix/FileDescriptor" static jmethodID posId = NULL; @@ -278,11 +280,13 @@ static const JNINativeMethod method_table[] = { static const jint method_table_size = sizeof(method_table) / sizeof(method_table[0]); // JNI Method Registration Table End -jint netty_unix_filedescriptor_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { +static jint netty_unix_filedescriptor_JNI_OnLoad0(JNIEnv* env, const char* packagePrefix, int registerNative) { int ret = JNI_ERR; void* mem = NULL; - if (netty_jni_util_register_natives(env, packagePrefix, FILEDESCRIPTOR_CLASSNAME, method_table, method_table_size) != 0) { - goto done; + if (registerNative) { + if (netty_jni_util_register_natives(env, packagePrefix, FILEDESCRIPTOR_CLASSNAME, method_table, method_table_size) != 0) { + goto done; + } } if ((mem = malloc(1)) == NULL) { goto done; @@ -316,6 +320,24 @@ jint netty_unix_filedescriptor_JNI_OnLoad(JNIEnv* env, const char* packagePrefix return ret; } +static void netty_unix_filedescriptor_JNI_OnUnLoad0(JNIEnv* env, const char* packagePrefix, int unregisterNative) { + if (unregisterNative) { + netty_jni_util_unregister_natives(env, packagePrefix, FILEDESCRIPTOR_CLASSNAME); + } +} + +jint netty_unix_filedescriptor_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { + return netty_unix_filedescriptor_JNI_OnLoad0(env, packagePrefix, 0); +} + void netty_unix_filedescriptor_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { - netty_jni_util_unregister_natives(env, packagePrefix, FILEDESCRIPTOR_CLASSNAME); + return netty_unix_filedescriptor_JNI_OnUnLoad0(env, packagePrefix, 0); +} + +jint netty_unix_filedescriptor_internal_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { + return netty_unix_filedescriptor_JNI_OnLoad0(env, packagePrefix, 1); +} + +void netty_unix_filedescriptor_internal_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { + return netty_unix_filedescriptor_JNI_OnUnLoad0(env, packagePrefix, 1); } diff --git a/transport-native-unix-common/src/main/c/netty_unix_limits.c b/transport-native-unix-common/src/main/c/netty_unix_limits.c index 26756fba940d..8d170c95301f 100644 --- a/transport-native-unix-common/src/main/c/netty_unix_limits.c +++ b/transport-native-unix-common/src/main/c/netty_unix_limits.c @@ -21,6 +21,7 @@ #include "netty_unix_limits.h" #include "netty_unix_util.h" #include "netty_jni_util.h" +#include "internal/netty_unix_limits_internal.h" #define LIMITS_CLASSNAME "io/netty/channel/unix/LimitsStaticallyReferencedJniMethods" @@ -69,19 +70,39 @@ static const JNINativeMethod statically_referenced_fixed_method_table[] = { static const jint statically_referenced_fixed_method_table_size = sizeof(statically_referenced_fixed_method_table) / sizeof(statically_referenced_fixed_method_table[0]); // JNI Method Registration Table End -jint netty_unix_limits_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { - // We must register the statically referenced methods first! - if (netty_jni_util_register_natives(env, - packagePrefix, - LIMITS_CLASSNAME, - statically_referenced_fixed_method_table, - statically_referenced_fixed_method_table_size) != 0) { - return JNI_ERR; +static jint netty_unix_limits_JNI_OnLoad0(JNIEnv* env, const char* packagePrefix, int registerNative) { + if (registerNative) { + // We must register the statically referenced methods first! + if (netty_jni_util_register_natives(env, + packagePrefix, + LIMITS_CLASSNAME, + statically_referenced_fixed_method_table, + statically_referenced_fixed_method_table_size) != 0) { + return JNI_ERR; + } } return NETTY_JNI_UTIL_JNI_VERSION; } +static void netty_unix_limits_JNI_OnUnLoad0(JNIEnv* env, const char* packagePrefix, int unregisterNative) { + if (unregisterNative) { + netty_jni_util_unregister_natives(env, packagePrefix, LIMITS_CLASSNAME); + } +} + +jint netty_unix_limits_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { + return netty_unix_limits_JNI_OnLoad0(env, packagePrefix, 0); +} + void netty_unix_limits_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { - netty_jni_util_unregister_natives(env, packagePrefix, LIMITS_CLASSNAME); + netty_unix_limits_JNI_OnUnLoad0(env, packagePrefix, 0); +} + +jint netty_unix_limits_internal_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { + return netty_unix_limits_JNI_OnLoad0(env, packagePrefix, 1); +} + +void netty_unix_limits_internal_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { + netty_unix_limits_JNI_OnUnLoad0(env, packagePrefix, 1); } diff --git a/transport-native-unix-common/src/main/c/netty_unix_native.c b/transport-native-unix-common/src/main/c/netty_unix_native.c new file mode 100644 index 000000000000..5bce1ae431c2 --- /dev/null +++ b/transport-native-unix-common/src/main/c/netty_unix_native.c @@ -0,0 +1,124 @@ +/* + * Copyright 2020 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +#include + +#include "netty_unix_buffer.h" +#include "netty_unix_errors.h" +#include "netty_unix_filedescriptor.h" +#include "netty_unix_jni.h" +#include "netty_unix_limits.h" +#include "netty_unix_socket.h" +#include "netty_unix_util.h" + +#include "internal/netty_unix_buffer_internal.h" +#include "internal/netty_unix_errors_internal.h" +#include "internal/netty_unix_filedescriptor_internal.h" +#include "internal/netty_unix_limits_internal.h" +#include "internal/netty_unix_socket_internal.h" + +// Add define if NETTY_BUILD_STATIC is defined so it is picked up in netty_jni_util.c +#ifdef NETTY_BUILD_STATIC +#define NETTY_JNI_UTIL_BUILD_STATIC +#endif + +static jint netty_unix_native_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { + int ret = JNI_ERR; + int limitsOnLoadCalled = 0; + int errorsOnLoadCalled = 0; + int filedescriptorOnLoadCalled = 0; + int socketOnLoadCalled = 0; + int bufferOnLoadCalled = 0; + + // Load all c modules that we depend upon + if (netty_unix_limits_internal_JNI_OnLoad(env, packagePrefix) == JNI_ERR) { + goto done; + } + limitsOnLoadCalled = 1; + + if (netty_unix_errors_internal_JNI_OnLoad(env, packagePrefix) == JNI_ERR) { + goto done; + } + errorsOnLoadCalled = 1; + + if (netty_unix_filedescriptor_internal_JNI_OnLoad(env, packagePrefix) == JNI_ERR) { + goto done; + } + filedescriptorOnLoadCalled = 1; + + if (netty_unix_socket_internal_JNI_OnLoad(env, packagePrefix) == JNI_ERR) { + goto done; + } + socketOnLoadCalled = 1; + + if (netty_unix_buffer_internal_JNI_OnLoad(env, packagePrefix) == JNI_ERR) { + goto done; + } + bufferOnLoadCalled = 1; + + ret = NETTY_JNI_UTIL_JNI_VERSION; +done: + if (ret == JNI_ERR) { + if (limitsOnLoadCalled == 1) { + netty_unix_limits_internal_JNI_OnUnLoad(env, packagePrefix); + } + if (errorsOnLoadCalled == 1) { + netty_unix_errors_internal_JNI_OnUnLoad(env, packagePrefix); + } + if (filedescriptorOnLoadCalled == 1) { + netty_unix_filedescriptor_internal_JNI_OnUnLoad(env, packagePrefix); + } + if (socketOnLoadCalled == 1) { + netty_unix_socket_internal_JNI_OnUnLoad(env, packagePrefix); + } + if (bufferOnLoadCalled == 1) { + netty_unix_buffer_internal_JNI_OnUnLoad(env, packagePrefix); + } + } + return ret; +} + +static void netty_unix_native_JNI_OnUnload(JNIEnv* env, const char* packagePrefix) { + netty_unix_limits_internal_JNI_OnUnLoad(env, packagePrefix); + netty_unix_errors_internal_JNI_OnUnLoad(env, packagePrefix); + netty_unix_filedescriptor_internal_JNI_OnUnLoad(env, packagePrefix); + netty_unix_socket_internal_JNI_OnUnLoad(env, packagePrefix); + netty_unix_buffer_internal_JNI_OnUnLoad(env, packagePrefix); +} + +// Invoked by the JVM when statically linked + +// We build with -fvisibility=hidden so ensure we mark everything that needs to be visible with JNIEXPORT +// https://mail.openjdk.java.net/pipermail/core-libs-dev/2013-February/014549.html + +// Invoked by the JVM when statically linked +JNIEXPORT jint JNI_OnLoad_netty_transport_native_unix(JavaVM* vm, void* reserved) { + return netty_jni_util_JNI_OnLoad(vm, reserved, "netty_transport_native_unix", netty_unix_native_JNI_OnLoad); +} + +// Invoked by the JVM when statically linked +JNIEXPORT void JNI_OnUnload_netty_transport_native_unix(JavaVM* vm, void* reserved) { + netty_jni_util_JNI_OnUnload(vm, reserved, netty_unix_native_JNI_OnUnload); +} + +#ifndef NETTY_BUILD_STATIC +JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { + return netty_jni_util_JNI_OnLoad(vm, reserved, "netty_transport_native_unix", netty_unix_native_JNI_OnLoad); +} + +JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved) { + netty_jni_util_JNI_OnUnload(vm, reserved, netty_unix_native_JNI_OnUnload); +} +#endif /* NETTY_BUILD_STATIC */ diff --git a/transport-native-unix-common/src/main/c/netty_unix_socket.c b/transport-native-unix-common/src/main/c/netty_unix_socket.c index da313eb65f7e..b7fac6e63989 100644 --- a/transport-native-unix-common/src/main/c/netty_unix_socket.c +++ b/transport-native-unix-common/src/main/c/netty_unix_socket.c @@ -32,6 +32,8 @@ #include "netty_unix_util.h" #include "netty_jni_util.h" +#include "internal/netty_unix_socket_internal.h" + #define SOCKET_CLASSNAME "io/netty/channel/unix/Socket" // Define SO_REUSEPORT if not found to fix build issues. // See https://github.com/netty/netty/issues/2558 @@ -1053,20 +1055,23 @@ static JNINativeMethod* createDynamicMethodsTable(const char* packagePrefix) { // JNI Method Registration Table End -jint netty_unix_socket_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { +static jint netty_unix_socket_JNI_OnLoad0(JNIEnv* env, const char* packagePrefix, int registerNative) { int ret = JNI_ERR; char* nettyClassName = NULL; void* mem = NULL; - JNINativeMethod* dynamicMethods = createDynamicMethodsTable(packagePrefix); - if (dynamicMethods == NULL) { - goto done; - } - if (netty_jni_util_register_natives(env, - packagePrefix, - SOCKET_CLASSNAME, - dynamicMethods, - dynamicMethodsTableSize()) != 0) { - goto done; + JNINativeMethod* dynamicMethods = NULL; + if (registerNative) { + dynamicMethods = createDynamicMethodsTable(packagePrefix); + if (dynamicMethods == NULL) { + goto done; + } + if (netty_jni_util_register_natives(env, + packagePrefix, + SOCKET_CLASSNAME, + dynamicMethods, + dynamicMethodsTableSize()) != 0) { + goto done; + } } NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/unix/DatagramSocketAddress", nettyClassName, done); @@ -1095,15 +1100,36 @@ jint netty_unix_socket_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { ret = NETTY_JNI_UTIL_JNI_VERSION; done: - netty_jni_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize()); + if (registerNative) { + netty_jni_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize()); + } free(nettyClassName); free(mem); return ret; } -void netty_unix_socket_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { +static void netty_unix_socket_JNI_OnUnLoad0(JNIEnv* env, const char* packagePrefix, int unregisterNative) { NETTY_JNI_UTIL_UNLOAD_CLASS(env, datagramSocketAddressClass); NETTY_JNI_UTIL_UNLOAD_CLASS(env, inetSocketAddressClass); - netty_jni_util_unregister_natives(env, packagePrefix, SOCKET_CLASSNAME); + if (unregisterNative) { + netty_jni_util_unregister_natives(env, packagePrefix, SOCKET_CLASSNAME); + } +} + +jint netty_unix_socket_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { + return netty_unix_socket_JNI_OnLoad0(env, packagePrefix, 0); +} + +void netty_unix_socket_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { + netty_unix_socket_JNI_OnUnLoad0(env, packagePrefix, 0); +} + + +jint netty_unix_socket_internal_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { + return netty_unix_socket_JNI_OnLoad0(env, packagePrefix, 1); +} + +void netty_unix_socket_internal_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { + netty_unix_socket_JNI_OnUnLoad0(env, packagePrefix, 1); } diff --git a/transport-native-unix-common/src/main/java/io/netty/channel/unix/FileDescriptor.java b/transport-native-unix-common/src/main/java/io/netty/channel/unix/FileDescriptor.java index e397aa3fae5f..f26ffaf44f58 100644 --- a/transport-native-unix-common/src/main/java/io/netty/channel/unix/FileDescriptor.java +++ b/transport-native-unix-common/src/main/java/io/netty/channel/unix/FileDescriptor.java @@ -51,6 +51,7 @@ public class FileDescriptor { final int fd; public FileDescriptor(int fd) { + Unix.ensureAvailability(); checkPositiveOrZero(fd, "fd"); this.fd = fd; } diff --git a/transport-native-unix-common/src/main/java/io/netty/channel/unix/IovArray.java b/transport-native-unix-common/src/main/java/io/netty/channel/unix/IovArray.java index 6071cccc9fb5..93fbf092f1af 100644 --- a/transport-native-unix-common/src/main/java/io/netty/channel/unix/IovArray.java +++ b/transport-native-unix-common/src/main/java/io/netty/channel/unix/IovArray.java @@ -66,7 +66,7 @@ public final class IovArray implements MessageProcessor { private final ByteBuf memory; private int count; private long size; - private long maxBytes = SSIZE_MAX; + private long maxBytes; public IovArray() { this(Unpooled.wrappedBuffer(Buffer.allocateDirectWithNativeOrder(MAX_CAPACITY)).setIndex(0, 0)); @@ -74,6 +74,7 @@ public IovArray() { @SuppressWarnings("deprecation") public IovArray(ByteBuf memory) { + Unix.ensureAvailability(); assert memory.writerIndex() == 0; assert memory.readerIndex() == 0; this.memory = PlatformDependent.hasUnsafe() ? memory : memory.order( @@ -84,6 +85,7 @@ public IovArray(ByteBuf memory) { // Fallback to using JNI as we were not be able to access the address otherwise. memoryAddress = Buffer.memoryAddress(memory.internalNioBuffer(0, memory.capacity())); } + maxBytes = SSIZE_MAX; } public void clear() { diff --git a/transport-native-unix-common/src/main/java/io/netty/channel/unix/Unix.java b/transport-native-unix-common/src/main/java/io/netty/channel/unix/Unix.java new file mode 100644 index 000000000000..b818c80639b1 --- /dev/null +++ b/transport-native-unix-common/src/main/java/io/netty/channel/unix/Unix.java @@ -0,0 +1,128 @@ +/* + * Copyright 2014 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.channel.unix; + +import io.netty.util.internal.NativeLibraryLoader; +import io.netty.util.internal.PlatformDependent; +import io.netty.util.internal.SystemPropertyUtil; +import io.netty.util.internal.ThrowableUtil; +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; + +/** + * Tells if {@code netty-transport-native-unix} is + * supported. + */ +public final class Unix { + private static final InternalLogger logger = InternalLoggerFactory.getInstance(Unix.class); + private static final Throwable UNAVAILABILITY_CAUSE; + + static { + Throwable cause = null; + 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 + // loaded by the application. + LimitsStaticallyReferencedJniMethods.udsSunPathSize(); + } 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(); + } catch (Throwable error) { + cause = error; + } + UNAVAILABILITY_CAUSE = cause; + } + + private static void loadNativeLibrary() { + String name = SystemPropertyUtil.get("os.name").toLowerCase(Locale.UK).trim(); + if (!name.startsWith("linux") && !name.startsWith("osx") && !name.startsWith("mac") + && !name.endsWith("bsd")) { + throw new IllegalStateException("Only supported on Linux/MacOS/BSD"); + } + String staticLibName = "netty_transport_native_unix"; + String sharedLibName = staticLibName + '_' + PlatformDependent.normalizedOs() + + '_' + PlatformDependent.normalizedArch(); + ClassLoader cl = PlatformDependent.getClassLoader(Unix.class); + try { + NativeLibraryLoader.load(sharedLibName, cl); + } catch (UnsatisfiedLinkError e1) { + try { + NativeLibraryLoader.load(staticLibName, cl); + logger.debug("Failed to load {}", sharedLibName, e1); + } catch (UnsatisfiedLinkError e2) { + ThrowableUtil.addSuppressed(e1, e2); + throw e1; + } + } + } + /** + * Returns {@code true} if and only if the {@code + * netty_transport_native_unix} is available. + */ + public static boolean isAvailable() { + return UNAVAILABILITY_CAUSE == null; + } + + /** + * Ensure that {@code netty_transport_native_unix} is + * available. + * + * @throws UnsatisfiedLinkError if unavailable + */ + public static void ensureAvailability() { + if (UNAVAILABILITY_CAUSE != null) { + throw (Error) new UnsatisfiedLinkError( + "failed to load the required native library").initCause(UNAVAILABILITY_CAUSE); + } + } + + /** + * Returns the cause of unavailability of + * {@code netty_transport_native_unix}. + * + * @return the cause if unavailable. {@code null} if available. + */ + public static Throwable unavailabilityCause() { + return UNAVAILABILITY_CAUSE; + } + + private Unix() { + } +}