From a63faa4fa1ae08efc391e9bcf461ab699a5d7efd Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Thu, 29 Oct 2020 16:36:07 +0100 Subject: [PATCH] Use netty-jni-util and so remove a lot of duplication (#10735) Motivation: We had a lot of duplication in our jni code which was mostly due macros but also related to how we support shading. By using netty-jni-util we can share all the code between netty and netty-tcnative ( and possible other jni based netty projects in the future). Modifications: - Use netty-jni-util and re-use its macros / functions - Remove duplicated code - Adjust build files Result: Less code duplication for JNI --- .../src/main/c/netty_resolver_dns_macos.c | 5 + transport-native-epoll/pom.xml | 2 +- .../src/main/c/netty_epoll_linuxsocket.c | 50 +++--- .../src/main/c/netty_epoll_native.c | 105 ++++--------- .../src/main/c/netty_kqueue_bsdsocket.c | 54 +++---- .../src/main/c/netty_kqueue_eventarray.c | 6 +- .../src/main/c/netty_kqueue_native.c | 77 +++------- transport-native-unix-common/Makefile | 12 +- transport-native-unix-common/pom.xml | 46 ++++++ .../src/main/c/netty_unix_buffer.c | 7 +- .../src/main/c/netty_unix_errors.c | 39 ++--- .../src/main/c/netty_unix_filedescriptor.c | 15 +- .../src/main/c/netty_unix_jni.h | 4 - .../src/main/c/netty_unix_limits.c | 7 +- .../src/main/c/netty_unix_socket.c | 39 ++--- .../src/main/c/netty_unix_util.c | 145 ------------------ .../src/main/c/netty_unix_util.h | 92 +---------- 17 files changed, 227 insertions(+), 478 deletions(-) diff --git a/resolver-dns-native-macos/src/main/c/netty_resolver_dns_macos.c b/resolver-dns-native-macos/src/main/c/netty_resolver_dns_macos.c index a3f7541eb0..06dd65ee9b 100644 --- a/resolver-dns-native-macos/src/main/c/netty_resolver_dns_macos.c +++ b/resolver-dns-native-macos/src/main/c/netty_resolver_dns_macos.c @@ -25,6 +25,11 @@ #include "netty_unix_socket.h" #include "netty_unix_errors.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 jclass dnsResolverClass = NULL; static jclass byteArrayClass = NULL; static jclass stringClass = NULL; diff --git a/transport-native-epoll/pom.xml b/transport-native-epoll/pom.xml index 75ec55cbfa..4e7b9e28fe 100644 --- a/transport-native-epoll/pom.xml +++ b/transport-native-epoll/pom.xml @@ -35,7 +35,7 @@ ${unix.common.lib.dir}/META-INF/native/lib ${unix.common.lib.dir}/META-INF/native/include CFLAGS=-O3 -Werror -fno-omit-frame-pointer -Wunused-variable -fvisibility=hidden -I${unix.common.include.unpacked.dir} - LDFLAGS=-L${unix.common.lib.unpacked.dir} -Wl,--no-as-needed -lrt -Wl,--whole-archive -l${unix.common.lib.name} -Wl,--no-whole-archive + LDFLAGS=-L${unix.common.lib.unpacked.dir} -Wl,--no-as-needed -lrt -ldl -Wl,--whole-archive -l${unix.common.lib.name} -Wl,--no-whole-archive ${project.basedir}/src/main/c true diff --git a/transport-native-epoll/src/main/c/netty_epoll_linuxsocket.c b/transport-native-epoll/src/main/c/netty_epoll_linuxsocket.c index 90ada5ddf3..9e7cbd8bf2 100644 --- a/transport-native-epoll/src/main/c/netty_epoll_linuxsocket.c +++ b/transport-native-epoll/src/main/c/netty_epoll_linuxsocket.c @@ -723,22 +723,22 @@ static JNINativeMethod* createDynamicMethodsTable(const char* packagePrefix) { memcpy(dynamicMethods, fixed_method_table, sizeof(fixed_method_table)); JNINativeMethod* dynamicMethod = &dynamicMethods[fixed_method_table_size]; - NETTY_PREPEND(packagePrefix, "io/netty/channel/unix/PeerCredentials;", dynamicTypeName, error); - NETTY_PREPEND("(I)L", dynamicTypeName, dynamicMethod->signature, error); + NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/unix/PeerCredentials;", dynamicTypeName, error); + NETTY_JNI_UTIL_PREPEND("(I)L", dynamicTypeName, dynamicMethod->signature, error); dynamicMethod->name = "getPeerCredentials"; dynamicMethod->fnPtr = (void *) netty_epoll_linuxsocket_getPeerCredentials; - netty_unix_util_free_dynamic_name(&dynamicTypeName); + netty_jni_util_free_dynamic_name(&dynamicTypeName); ++dynamicMethod; - NETTY_PREPEND(packagePrefix, "io/netty/channel/DefaultFileRegion;JJJ)J", dynamicTypeName, error); - NETTY_PREPEND("(IL", dynamicTypeName, dynamicMethod->signature, error); + NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/DefaultFileRegion;JJJ)J", dynamicTypeName, error); + NETTY_JNI_UTIL_PREPEND("(IL", dynamicTypeName, dynamicMethod->signature, error); dynamicMethod->name = "sendFile"; dynamicMethod->fnPtr = (void *) netty_epoll_linuxsocket_sendFile; - netty_unix_util_free_dynamic_name(&dynamicTypeName); + netty_jni_util_free_dynamic_name(&dynamicTypeName); return dynamicMethods; error: free(dynamicTypeName); - netty_unix_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize()); + netty_jni_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize()); return NULL; } @@ -755,7 +755,7 @@ jint netty_epoll_linuxsocket_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) if (dynamicMethods == NULL) { goto done; } - if (netty_unix_util_register_natives(env, + if (netty_jni_util_register_natives(env, packagePrefix, LINUXSOCKET_CLASSNAME, dynamicMethods, @@ -763,35 +763,35 @@ jint netty_epoll_linuxsocket_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) goto done; } - NETTY_PREPEND(packagePrefix, "io/netty/channel/unix/PeerCredentials", nettyClassName, done); - NETTY_LOAD_CLASS(env, peerCredentialsClass, nettyClassName, done); - netty_unix_util_free_dynamic_name(&nettyClassName); + NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/unix/PeerCredentials", nettyClassName, done); + NETTY_JNI_UTIL_LOAD_CLASS(env, peerCredentialsClass, nettyClassName, done); + netty_jni_util_free_dynamic_name(&nettyClassName); - NETTY_GET_METHOD(env, peerCredentialsClass, peerCredentialsMethodId, "", "(II[I)V", done); + NETTY_JNI_UTIL_GET_METHOD(env, peerCredentialsClass, peerCredentialsMethodId, "", "(II[I)V", done); - NETTY_PREPEND(packagePrefix, "io/netty/channel/DefaultFileRegion", nettyClassName, done); - NETTY_FIND_CLASS(env, fileRegionCls, nettyClassName, done); - netty_unix_util_free_dynamic_name(&nettyClassName); + NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/DefaultFileRegion", nettyClassName, done); + NETTY_JNI_UTIL_FIND_CLASS(env, fileRegionCls, nettyClassName, done); + netty_jni_util_free_dynamic_name(&nettyClassName); - NETTY_GET_FIELD(env, fileRegionCls, fileChannelFieldId, "file", "Ljava/nio/channels/FileChannel;", done); - NETTY_GET_FIELD(env, fileRegionCls, transferredFieldId, "transferred", "J", done); + NETTY_JNI_UTIL_GET_FIELD(env, fileRegionCls, fileChannelFieldId, "file", "Ljava/nio/channels/FileChannel;", done); + NETTY_JNI_UTIL_GET_FIELD(env, fileRegionCls, transferredFieldId, "transferred", "J", done); - NETTY_FIND_CLASS(env, fileChannelCls, "sun/nio/ch/FileChannelImpl", done); - NETTY_GET_FIELD(env, fileChannelCls, fileDescriptorFieldId, "fd", "Ljava/io/FileDescriptor;", done); + NETTY_JNI_UTIL_FIND_CLASS(env, fileChannelCls, "sun/nio/ch/FileChannelImpl", done); + NETTY_JNI_UTIL_GET_FIELD(env, fileChannelCls, fileDescriptorFieldId, "fd", "Ljava/io/FileDescriptor;", done); - NETTY_FIND_CLASS(env, fileDescriptorCls, "java/io/FileDescriptor", done); - NETTY_GET_FIELD(env, fileDescriptorCls, fdFieldId, "fd", "I", done); + NETTY_JNI_UTIL_FIND_CLASS(env, fileDescriptorCls, "java/io/FileDescriptor", done); + NETTY_JNI_UTIL_GET_FIELD(env, fileDescriptorCls, fdFieldId, "fd", "I", done); - ret = NETTY_JNI_VERSION; + ret = NETTY_JNI_UTIL_JNI_VERSION; done: - netty_unix_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize()); + netty_jni_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize()); free(nettyClassName); return ret; } void netty_epoll_linuxsocket_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { - NETTY_UNLOAD_CLASS(env, peerCredentialsClass); + NETTY_JNI_UTIL_UNLOAD_CLASS(env, peerCredentialsClass); - netty_unix_util_unregister_natives(env, packagePrefix, LINUXSOCKET_CLASSNAME); + netty_jni_util_unregister_natives(env, packagePrefix, LINUXSOCKET_CLASSNAME); } diff --git a/transport-native-epoll/src/main/c/netty_epoll_native.c b/transport-native-epoll/src/main/c/netty_epoll_native.c index 594713e911..7ce49aab9f 100644 --- a/transport-native-epoll/src/main/c/netty_epoll_native.c +++ b/transport-native-epoll/src/main/c/netty_epoll_native.c @@ -49,6 +49,11 @@ #include "netty_unix_socket.h" #include "netty_unix_util.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 + #define STATICALLY_CLASSNAME "io/netty/channel/epoll/NativeStaticallyReferencedJniMethods" #define NATIVE_CLASSNAME "io/netty/channel/epoll/Native" @@ -101,7 +106,6 @@ static jfieldID packetScopeIdFieldId = NULL; static jfieldID packetPortFieldId = NULL; static jfieldID packetMemoryAddressFieldId = NULL; static jfieldID packetCountFieldId = NULL; -static char* staticPackagePrefix = NULL; // util methods static int getSysctlValue(const char * property, int* returnValue) { @@ -571,23 +575,23 @@ static JNINativeMethod* createDynamicMethodsTable(const char* packagePrefix) { memcpy(dynamicMethods, fixed_method_table, sizeof(fixed_method_table)); JNINativeMethod* dynamicMethod = &dynamicMethods[fixed_method_table_size]; - NETTY_PREPEND(packagePrefix, "io/netty/channel/epoll/NativeDatagramPacketArray$NativeDatagramPacket;II)I", dynamicTypeName, error); - NETTY_PREPEND("(IZ[L", dynamicTypeName, dynamicMethod->signature, error); + NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/epoll/NativeDatagramPacketArray$NativeDatagramPacket;II)I", dynamicTypeName, error); + NETTY_JNI_UTIL_PREPEND("(IZ[L", dynamicTypeName, dynamicMethod->signature, error); dynamicMethod->name = "sendmmsg0"; dynamicMethod->fnPtr = (void *) netty_epoll_native_sendmmsg0; - netty_unix_util_free_dynamic_name(&dynamicTypeName); + netty_jni_util_free_dynamic_name(&dynamicTypeName); ++dynamicMethod; - NETTY_PREPEND(packagePrefix, "io/netty/channel/epoll/NativeDatagramPacketArray$NativeDatagramPacket;II)I", dynamicTypeName, error); - NETTY_PREPEND("(IZ[L", dynamicTypeName, dynamicMethod->signature, error); + NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/epoll/NativeDatagramPacketArray$NativeDatagramPacket;II)I", dynamicTypeName, error); + NETTY_JNI_UTIL_PREPEND("(IZ[L", dynamicTypeName, dynamicMethod->signature, error); dynamicMethod->name = "recvmmsg0"; dynamicMethod->fnPtr = (void *) netty_epoll_native_recvmmsg0; - netty_unix_util_free_dynamic_name(&dynamicTypeName); + netty_jni_util_free_dynamic_name(&dynamicTypeName); return dynamicMethods; error: free(dynamicTypeName); - netty_unix_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize()); + netty_jni_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize()); return NULL; } @@ -608,7 +612,7 @@ static jint netty_epoll_native_JNI_OnLoad(JNIEnv* env, const char* packagePrefix JNINativeMethod* dynamicMethods = NULL; // We must register the statically referenced methods first! - if (netty_unix_util_register_natives(env, + if (netty_jni_util_register_natives(env, packagePrefix, STATICALLY_CLASSNAME, statically_referenced_fixed_method_table, @@ -623,7 +627,7 @@ static jint netty_epoll_native_JNI_OnLoad(JNIEnv* env, const char* packagePrefix goto done; } - if (netty_unix_util_register_natives(env, + if (netty_jni_util_register_natives(env, packagePrefix, NATIVE_CLASSNAME, dynamicMethods, @@ -664,29 +668,29 @@ static jint netty_epoll_native_JNI_OnLoad(JNIEnv* env, const char* packagePrefix linuxsocketOnLoadCalled = 1; // Initialize this module - NETTY_PREPEND(packagePrefix, "io/netty/channel/epoll/NativeDatagramPacketArray$NativeDatagramPacket", nettyClassName, done); - NETTY_FIND_CLASS(env, nativeDatagramPacketCls, nettyClassName, done); - netty_unix_util_free_dynamic_name(&nettyClassName); + NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/epoll/NativeDatagramPacketArray$NativeDatagramPacket", nettyClassName, done); + NETTY_JNI_UTIL_FIND_CLASS(env, nativeDatagramPacketCls, nettyClassName, done); + netty_jni_util_free_dynamic_name(&nettyClassName); - NETTY_GET_FIELD(env, nativeDatagramPacketCls, packetAddrFieldId, "addr", "[B", done); - NETTY_GET_FIELD(env, nativeDatagramPacketCls, packetAddrLenFieldId, "addrLen", "I", done); - NETTY_GET_FIELD(env, nativeDatagramPacketCls, packetScopeIdFieldId, "scopeId", "I", done); - NETTY_GET_FIELD(env, nativeDatagramPacketCls, packetPortFieldId, "port", "I", done); - NETTY_GET_FIELD(env, nativeDatagramPacketCls, packetMemoryAddressFieldId, "memoryAddress", "J", done); - NETTY_GET_FIELD(env, nativeDatagramPacketCls, packetCountFieldId, "count", "I", done); + NETTY_JNI_UTIL_GET_FIELD(env, nativeDatagramPacketCls, packetAddrFieldId, "addr", "[B", done); + NETTY_JNI_UTIL_GET_FIELD(env, nativeDatagramPacketCls, packetAddrLenFieldId, "addrLen", "I", done); + NETTY_JNI_UTIL_GET_FIELD(env, nativeDatagramPacketCls, packetScopeIdFieldId, "scopeId", "I", done); + NETTY_JNI_UTIL_GET_FIELD(env, nativeDatagramPacketCls, packetPortFieldId, "port", "I", done); + NETTY_JNI_UTIL_GET_FIELD(env, nativeDatagramPacketCls, packetMemoryAddressFieldId, "memoryAddress", "J", done); + NETTY_JNI_UTIL_GET_FIELD(env, nativeDatagramPacketCls, packetCountFieldId, "count", "I", done); - ret = NETTY_JNI_VERSION; + ret = NETTY_JNI_UTIL_JNI_VERSION; done: - netty_unix_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize()); + netty_jni_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize()); free(nettyClassName); if (ret == JNI_ERR) { if (staticallyRegistered == 1) { - netty_unix_util_unregister_natives(env, packagePrefix, STATICALLY_CLASSNAME); + netty_jni_util_unregister_natives(env, packagePrefix, STATICALLY_CLASSNAME); } if (nativeRegistered == 1) { - netty_unix_util_unregister_natives(env, packagePrefix, NATIVE_CLASSNAME); + netty_jni_util_unregister_natives(env, packagePrefix, NATIVE_CLASSNAME); } if (limitsOnLoadCalled == 1) { netty_unix_limits_JNI_OnUnLoad(env, packagePrefix); @@ -716,7 +720,7 @@ done: return ret; } -static void netty_epoll_native_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { +static void netty_epoll_native_JNI_OnUnload(JNIEnv* env, const char* packagePrefix) { netty_unix_limits_JNI_OnUnLoad(env, packagePrefix); netty_unix_errors_JNI_OnUnLoad(env, packagePrefix); netty_unix_filedescriptor_JNI_OnUnLoad(env, packagePrefix); @@ -731,72 +735,31 @@ static void netty_epoll_native_JNI_OnUnLoad(JNIEnv* env, const char* packagePref packetMemoryAddressFieldId = NULL; packetCountFieldId = NULL; - netty_unix_util_unregister_natives(env, packagePrefix, STATICALLY_CLASSNAME); - netty_unix_util_unregister_natives(env, packagePrefix, NATIVE_CLASSNAME); + netty_jni_util_unregister_natives(env, packagePrefix, STATICALLY_CLASSNAME); + netty_jni_util_unregister_natives(env, packagePrefix, NATIVE_CLASSNAME); } // Invoked by the JVM when statically linked -static jint JNI_OnLoad_netty_transport_native_epoll0(JavaVM* vm, void* reserved) { - JNIEnv* env; - if ((*vm)->GetEnv(vm, (void**) &env, NETTY_JNI_VERSION) != JNI_OK) { - return JNI_ERR; - } - char* packagePrefix = NULL; -#ifndef NETTY_BUILD_STATIC - Dl_info dlinfo; - jint status = 0; - // We need to use an address of a function that is uniquely part of this library, so choose a static - // function. See https://github.com/netty/netty/issues/4840. - if (!dladdr((void*) netty_epoll_native_JNI_OnUnLoad, &dlinfo)) { - fprintf(stderr, "FATAL: transport-native-epoll JNI call to dladdr failed!\n"); - return JNI_ERR; - } - packagePrefix = netty_unix_util_parse_package_prefix(dlinfo.dli_fname, "netty_transport_native_epoll", &status); - if (status == JNI_ERR) { - fprintf(stderr, "FATAL: transport-native-epoll JNI encountered unexpected dlinfo.dli_fname: %s\n", dlinfo.dli_fname); - return JNI_ERR; - } -#endif /* NETTY_BUILD_STATIC */ - jint ret = netty_epoll_native_JNI_OnLoad(env, packagePrefix); - if (ret == JNI_ERR) { - free(packagePrefix); - staticPackagePrefix = NULL; - } else { - staticPackagePrefix = packagePrefix; - } - return ret; -} - -static void JNI_OnUnload_netty_transport_native_epoll0(JavaVM* vm, void* reserved) { - JNIEnv* env; - if ((*vm)->GetEnv(vm, (void**) &env, NETTY_JNI_VERSION) != JNI_OK) { - // Something is wrong but nothing we can do about this :( - return; - } - netty_epoll_native_JNI_OnUnLoad(env, staticPackagePrefix); - free(staticPackagePrefix); - staticPackagePrefix = NULL; -} // 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_epoll(JavaVM* vm, void* reserved) { - return JNI_OnLoad_netty_transport_native_epoll0(vm, reserved); + return netty_jni_util_JNI_OnLoad(vm, reserved, "netty_transport_native_epoll", netty_epoll_native_JNI_OnLoad); } // Invoked by the JVM when statically linked JNIEXPORT void JNI_OnUnload_netty_transport_native_epoll(JavaVM* vm, void* reserved) { - JNI_OnUnload_netty_transport_native_epoll0(vm, reserved); + netty_jni_util_JNI_OnUnload(vm, reserved, netty_epoll_native_JNI_OnUnload); } #ifndef NETTY_BUILD_STATIC JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { - return JNI_OnLoad_netty_transport_native_epoll0(vm, reserved); + return netty_jni_util_JNI_OnLoad(vm, reserved, "netty_transport_native_epoll", netty_epoll_native_JNI_OnLoad); } JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved) { - JNI_OnUnload_netty_transport_native_epoll0(vm, reserved); + netty_jni_util_JNI_OnUnload(vm, reserved, netty_epoll_native_JNI_OnUnload); } #endif /* NETTY_BUILD_STATIC */ diff --git a/transport-native-kqueue/src/main/c/netty_kqueue_bsdsocket.c b/transport-native-kqueue/src/main/c/netty_kqueue_bsdsocket.c index 3aa670893a..8b38b8859e 100644 --- a/transport-native-kqueue/src/main/c/netty_kqueue_bsdsocket.c +++ b/transport-native-kqueue/src/main/c/netty_kqueue_bsdsocket.c @@ -216,23 +216,23 @@ static JNINativeMethod* createDynamicMethodsTable(const char* packagePrefix) { memcpy(dynamicMethods, fixed_method_table, sizeof(fixed_method_table)); JNINativeMethod* dynamicMethod = &dynamicMethods[fixed_method_table_size]; - NETTY_PREPEND(packagePrefix, "io/netty/channel/DefaultFileRegion;JJJ)J", dynamicTypeName, error); - NETTY_PREPEND("(IL", dynamicTypeName, dynamicMethod->signature, error); + NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/DefaultFileRegion;JJJ)J", dynamicTypeName, error); + NETTY_JNI_UTIL_PREPEND("(IL", dynamicTypeName, dynamicMethod->signature, error); dynamicMethod->name = "sendFile"; dynamicMethod->fnPtr = (void *) netty_kqueue_bsdsocket_sendFile; - netty_unix_util_free_dynamic_name(&dynamicTypeName); + netty_jni_util_free_dynamic_name(&dynamicTypeName); ++dynamicMethod; - NETTY_PREPEND(packagePrefix, "io/netty/channel/unix/PeerCredentials;", dynamicTypeName, error); - NETTY_PREPEND("(I)L", dynamicTypeName, dynamicMethod->signature, error); + NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/unix/PeerCredentials;", dynamicTypeName, error); + NETTY_JNI_UTIL_PREPEND("(I)L", dynamicTypeName, dynamicMethod->signature, error); dynamicMethod->name = "getPeerCredentials"; dynamicMethod->fnPtr = (void *) netty_kqueue_bsdsocket_getPeerCredentials; - netty_unix_util_free_dynamic_name(&dynamicTypeName); + netty_jni_util_free_dynamic_name(&dynamicTypeName); return dynamicMethods; error: free(dynamicTypeName); - netty_unix_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize()); + netty_jni_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize()); return NULL; } @@ -249,7 +249,7 @@ jint netty_kqueue_bsdsocket_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { if (dynamicMethods == NULL) { goto done; } - if (netty_unix_util_register_natives(env, + if (netty_jni_util_register_natives(env, packagePrefix, BSDSOCKET_CLASSNAME, dynamicMethods, @@ -258,37 +258,37 @@ jint netty_kqueue_bsdsocket_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { } // Initialize this module - NETTY_PREPEND(packagePrefix, "io/netty/channel/DefaultFileRegion", nettyClassName, done); - NETTY_FIND_CLASS(env, fileRegionCls, nettyClassName, done); - netty_unix_util_free_dynamic_name(&nettyClassName); + NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/DefaultFileRegion", nettyClassName, done); + NETTY_JNI_UTIL_FIND_CLASS(env, fileRegionCls, nettyClassName, done); + netty_jni_util_free_dynamic_name(&nettyClassName); - NETTY_GET_FIELD(env, fileRegionCls, fileChannelFieldId, "file", "Ljava/nio/channels/FileChannel;", done); - NETTY_GET_FIELD(env, fileRegionCls, transferredFieldId, "transferred", "J", done); + NETTY_JNI_UTIL_GET_FIELD(env, fileRegionCls, fileChannelFieldId, "file", "Ljava/nio/channels/FileChannel;", done); + NETTY_JNI_UTIL_GET_FIELD(env, fileRegionCls, transferredFieldId, "transferred", "J", done); - NETTY_FIND_CLASS(env, fileChannelCls, "sun/nio/ch/FileChannelImpl", done); - NETTY_GET_FIELD(env, fileChannelCls, fileDescriptorFieldId, "fd", "Ljava/io/FileDescriptor;", done); + NETTY_JNI_UTIL_FIND_CLASS(env, fileChannelCls, "sun/nio/ch/FileChannelImpl", done); + NETTY_JNI_UTIL_GET_FIELD(env, fileChannelCls, fileDescriptorFieldId, "fd", "Ljava/io/FileDescriptor;", done); - NETTY_FIND_CLASS(env, fileDescriptorCls, "java/io/FileDescriptor", done); - NETTY_GET_FIELD(env, fileDescriptorCls, fdFieldId, "fd", "I", done); + NETTY_JNI_UTIL_FIND_CLASS(env, fileDescriptorCls, "java/io/FileDescriptor", done); + NETTY_JNI_UTIL_GET_FIELD(env, fileDescriptorCls, fdFieldId, "fd", "I", done); - NETTY_LOAD_CLASS(env, stringClass, "java/lang/String", done); + NETTY_JNI_UTIL_LOAD_CLASS(env, stringClass, "java/lang/String", done); - NETTY_PREPEND(packagePrefix, "io/netty/channel/unix/PeerCredentials", nettyClassName, done); - NETTY_LOAD_CLASS(env, peerCredentialsClass, nettyClassName, done); - netty_unix_util_free_dynamic_name(&nettyClassName); + NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/unix/PeerCredentials", nettyClassName, done); + NETTY_JNI_UTIL_LOAD_CLASS(env, peerCredentialsClass, nettyClassName, done); + netty_jni_util_free_dynamic_name(&nettyClassName); - NETTY_GET_METHOD(env, peerCredentialsClass, peerCredentialsMethodId, "", "(II[I)V", done); - ret = NETTY_JNI_VERSION; + NETTY_JNI_UTIL_GET_METHOD(env, peerCredentialsClass, peerCredentialsMethodId, "", "(II[I)V", done); + ret = NETTY_JNI_UTIL_JNI_VERSION; done: - netty_unix_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize()); + netty_jni_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize()); free(nettyClassName); return ret; } void netty_kqueue_bsdsocket_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { - NETTY_UNLOAD_CLASS(env, peerCredentialsClass); - NETTY_UNLOAD_CLASS(env, stringClass); + NETTY_JNI_UTIL_UNLOAD_CLASS(env, peerCredentialsClass); + NETTY_JNI_UTIL_UNLOAD_CLASS(env, stringClass); - netty_unix_util_unregister_natives(env, packagePrefix, BSDSOCKET_CLASSNAME); + netty_jni_util_unregister_natives(env, packagePrefix, BSDSOCKET_CLASSNAME); } diff --git a/transport-native-kqueue/src/main/c/netty_kqueue_eventarray.c b/transport-native-kqueue/src/main/c/netty_kqueue_eventarray.c index 63010a65f0..730e65899d 100644 --- a/transport-native-kqueue/src/main/c/netty_kqueue_eventarray.c +++ b/transport-native-kqueue/src/main/c/netty_kqueue_eventarray.c @@ -39,16 +39,16 @@ static const jint fixed_method_table_size = sizeof(fixed_method_table) / sizeof( // JNI Method Registration Table End jint netty_kqueue_eventarray_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { - if (netty_unix_util_register_natives(env, + if (netty_jni_util_register_natives(env, packagePrefix, EVENT_ARRAY_CLASSNAME, fixed_method_table, fixed_method_table_size) != 0) { return JNI_ERR; } - return NETTY_JNI_VERSION; + return NETTY_JNI_UTIL_JNI_VERSION; } void netty_kqueue_eventarray_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { - netty_unix_util_unregister_natives(env, packagePrefix, EVENT_ARRAY_CLASSNAME); + netty_jni_util_unregister_natives(env, packagePrefix, EVENT_ARRAY_CLASSNAME); } diff --git a/transport-native-kqueue/src/main/c/netty_kqueue_native.c b/transport-native-kqueue/src/main/c/netty_kqueue_native.c index 892b8d9f4c..0f7376ef3a 100644 --- a/transport-native-kqueue/src/main/c/netty_kqueue_native.c +++ b/transport-native-kqueue/src/main/c/netty_kqueue_native.c @@ -36,6 +36,11 @@ #include "netty_unix_socket.h" #include "netty_unix_util.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 + #define STATICALLY_CLASSNAME "io/netty/channel/kqueue/KQueueStaticallyReferencedJniMethods" #define NATIVE_CLASSNAME "io/netty/channel/kqueue/Native" @@ -71,8 +76,6 @@ static clockid_t waitClockId = 0; // initialized by netty_unix_util_initialize_wait_clock -static char* staticPackagePrefix; - static jint netty_kqueue_native_kqueueCreate(JNIEnv* env, jclass clazz) { jint kq = kqueue(); if (kq < 0) { @@ -281,7 +284,7 @@ static jint netty_kqueue_native_JNI_OnLoad(JNIEnv* env, const char* packagePrefi int eventarrayOnLoadCalled = 0; // We must register the statically referenced methods first! - if (netty_unix_util_register_natives(env, + if (netty_jni_util_register_natives(env, packagePrefix, STATICALLY_CLASSNAME, statically_referenced_fixed_method_table, @@ -291,11 +294,10 @@ static jint netty_kqueue_native_JNI_OnLoad(JNIEnv* env, const char* packagePrefi staticallyRegistered = 1; // Register the methods which are not referenced by static member variables - if (netty_unix_util_register_natives(env, packagePrefix, NATIVE_CLASSNAME, fixed_method_table, fixed_method_table_size) != 0) { + if (netty_jni_util_register_natives(env, packagePrefix, NATIVE_CLASSNAME, fixed_method_table, fixed_method_table_size) != 0) { goto error; } nativeRegistered = 1; - // Load all c modules that we depend upon if (netty_unix_limits_JNI_OnLoad(env, packagePrefix) == JNI_ERR) { goto error; @@ -336,16 +338,17 @@ static jint netty_kqueue_native_JNI_OnLoad(JNIEnv* env, const char* packagePrefi if (!netty_unix_util_initialize_wait_clock(&waitClockId)) { fprintf(stderr, "FATAL: could not find a clock for clock_gettime!\n"); + fflush(stderr); goto error; } - return NETTY_JNI_VERSION; + return NETTY_JNI_UTIL_JNI_VERSION; error: if (staticallyRegistered == 1) { - netty_unix_util_unregister_natives(env, packagePrefix, STATICALLY_CLASSNAME); + netty_jni_util_unregister_natives(env, packagePrefix, STATICALLY_CLASSNAME); } if (nativeRegistered == 1) { - netty_unix_util_unregister_natives(env, packagePrefix, NATIVE_CLASSNAME); + netty_jni_util_unregister_natives(env, packagePrefix, NATIVE_CLASSNAME); } if (limitsOnLoadCalled == 1) { netty_unix_limits_JNI_OnUnLoad(env, packagePrefix); @@ -371,10 +374,7 @@ error: return JNI_ERR; } -static void netty_kqueue_native_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { - netty_unix_util_unregister_natives(env, packagePrefix, STATICALLY_CLASSNAME); - netty_unix_util_unregister_natives(env, packagePrefix, NATIVE_CLASSNAME); - +static void netty_kqueue_native_JNI_OnUnload(JNIEnv* env, const char* packagePrefix) { netty_unix_limits_JNI_OnUnLoad(env, packagePrefix); netty_unix_errors_JNI_OnUnLoad(env, packagePrefix); netty_unix_filedescriptor_JNI_OnUnLoad(env, packagePrefix); @@ -382,50 +382,9 @@ static void netty_kqueue_native_JNI_OnUnLoad(JNIEnv* env, const char* packagePre netty_unix_buffer_JNI_OnUnLoad(env, packagePrefix); netty_kqueue_bsdsocket_JNI_OnUnLoad(env, packagePrefix); netty_kqueue_eventarray_JNI_OnUnLoad(env, packagePrefix); -} -static jint JNI_OnLoad_netty_transport_native_kqueue0(JavaVM* vm, void* reserved) { - JNIEnv* env; - if ((*vm)->GetEnv(vm, (void**) &env, NETTY_JNI_VERSION) != JNI_OK) { - return JNI_ERR; - } - - char* packagePrefix = NULL; -#ifndef NETTY_BUILD_STATIC - Dl_info dlinfo; - jint status = 0; - // We need to use an address of a function that is uniquely part of this library, so choose a static - // function. See https://github.com/netty/netty/issues/4840. - if (!dladdr((void*) netty_kqueue_native_JNI_OnUnLoad, &dlinfo)) { - fprintf(stderr, "FATAL: transport-native-kqueue JNI call to dladdr failed!\n"); - return JNI_ERR; - } - packagePrefix = netty_unix_util_parse_package_prefix(dlinfo.dli_fname, "netty_transport_native_kqueue", &status); - if (status == JNI_ERR) { - fprintf(stderr, "FATAL: transport-native-kqueue JNI encountered unexpected dlinfo.dli_fname: %s\n", dlinfo.dli_fname); - return JNI_ERR; - } -#endif /* NETTY_BUILD_STATIC */ - jint ret = netty_kqueue_native_JNI_OnLoad(env, packagePrefix); - if (ret == JNI_ERR) { - free(packagePrefix); - staticPackagePrefix = NULL; - } else { - staticPackagePrefix = packagePrefix; - } - - return ret; -} - -static void JNI_OnUnload_netty_transport_native_kqueue0(JavaVM* vm, void* reserved) { - JNIEnv* env; - if ((*vm)->GetEnv(vm, (void**) &env, NETTY_JNI_VERSION) != JNI_OK) { - // Something is wrong but nothing we can do about this :( - return; - } - netty_kqueue_native_JNI_OnUnLoad(env, staticPackagePrefix); - free(staticPackagePrefix); - staticPackagePrefix = NULL; + netty_jni_util_unregister_natives(env, packagePrefix, STATICALLY_CLASSNAME); + netty_jni_util_unregister_natives(env, packagePrefix, NATIVE_CLASSNAME); } // We build with -fvisibility=hidden so ensure we mark everything that needs to be visible with JNIEXPORT @@ -433,20 +392,20 @@ static void JNI_OnUnload_netty_transport_native_kqueue0(JavaVM* vm, void* reserv // Invoked by the JVM when statically linked JNIEXPORT jint JNI_OnLoad_netty_transport_native_kqueue(JavaVM* vm, void* reserved) { - return JNI_OnLoad_netty_transport_native_kqueue0(vm, reserved); + return netty_jni_util_JNI_OnLoad(vm, reserved, "netty_transport_native_kqueue", netty_kqueue_native_JNI_OnLoad); } // Invoked by the JVM when statically linked JNIEXPORT void JNI_OnUnload_netty_transport_native_kqueue(JavaVM* vm, void* reserved) { - JNI_OnUnload_netty_transport_native_kqueue0(vm, reserved); + netty_jni_util_JNI_OnUnload(vm, reserved, netty_kqueue_native_JNI_OnUnload); } #ifndef NETTY_BUILD_STATIC JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { - return JNI_OnLoad_netty_transport_native_kqueue0(vm, reserved); + return netty_jni_util_JNI_OnLoad(vm, reserved, "netty_transport_native_kqueue", netty_kqueue_native_JNI_OnLoad); } JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved) { - return JNI_OnUnload_netty_transport_native_kqueue0(vm, reserved); + netty_jni_util_JNI_OnUnload(vm, reserved, netty_kqueue_native_JNI_OnUnload); } #endif /* NETTY_BUILD_STATIC */ diff --git a/transport-native-unix-common/Makefile b/transport-native-unix-common/Makefile index 32aad97c65..8f9eade97d 100644 --- a/transport-native-unix-common/Makefile +++ b/transport-native-unix-common/Makefile @@ -23,14 +23,17 @@ # LIB_NAME - the name of the native library SRC_DIR = src/main/c +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) +CFLAGS += $(JNI_INCLUDES) -I$(UTIL_SRC_DIR) SRCS = $(wildcard $(SRC_DIR)/*.c) -OBJS = $(SRCS:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) +UTIL_SRCS = $(wildcard $(UTIL_SRC_DIR)/*.c) + +OBJS = $(SRCS:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) $(UTIL_SRCS:$(UTIL_SRC_DIR)/%.c=$(OBJ_DIR)/%.o) all: $(LIB) @@ -42,6 +45,11 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c mkdir -p $(OBJ_DIR) $(CC) -o $@ -c $< $(CFLAGS) +$(OBJ_DIR)/%.o: $(UTIL_SRC_DIR)/%.c + mkdir -p $(OBJ_DIR) + $(CC) -o $@ -c $< $(CFLAGS) + + clean: rm -rf $(LIB_DIR) $(OBJ_DIR) diff --git a/transport-native-unix-common/pom.xml b/transport-native-unix-common/pom.xml index 0621ec65f0..f42d9744c7 100644 --- a/transport-native-unix-common/pom.xml +++ b/transport-native-unix-common/pom.xml @@ -37,6 +37,8 @@ ar libnetty-unix-common ${project.basedir}/src/main/c + ${project.build.directory}/netty-jni-util + ${project.build.directory}/netty-jni-util/src/c ${project.build.directory}/native-jar-work ${project.build.directory}/native-objs-only ${project.build.directory}/native-lib-only @@ -46,6 +48,30 @@ + + + maven-scm-plugin + 1.11.2 + + + get-netty-jni-util + generate-sources + + checkout + + + ${jniUtilCheckoutDir} + developerConnection + scm:git:https://github.com/netty/netty-jni-util.git + 0.0.1 + tag + true + + + + + + org.codehaus.mojo @@ -104,6 +130,10 @@ + + + + @@ -175,6 +205,10 @@ + + + + @@ -240,6 +274,10 @@ + + + + @@ -310,6 +348,10 @@ + + + + @@ -380,6 +422,10 @@ + + + + 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 809db9246f..db922ab396 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 @@ -16,6 +16,7 @@ #include "netty_unix_jni.h" #include "netty_unix_util.h" #include "netty_unix_buffer.h" +#include "netty_jni_util.h" #define BUFFER_CLASSNAME "io/netty/channel/unix/Buffer" @@ -40,7 +41,7 @@ static const jint statically_referenced_fixed_method_table_size = sizeof(statica jint netty_unix_buffer_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { // We must register the statically referenced methods first! - if (netty_unix_util_register_natives(env, + if (netty_jni_util_register_natives(env, packagePrefix, BUFFER_CLASSNAME, statically_referenced_fixed_method_table, @@ -48,9 +49,9 @@ jint netty_unix_buffer_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { return JNI_ERR; } - return NETTY_JNI_VERSION; + return NETTY_JNI_UTIL_JNI_VERSION; } void netty_unix_buffer_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { - netty_unix_util_unregister_natives(env, packagePrefix, BUFFER_CLASSNAME); + netty_jni_util_unregister_natives(env, packagePrefix, BUFFER_CLASSNAME); } 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 17f1a5cf18..8ecc14760d 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 @@ -20,6 +20,7 @@ #include "netty_unix_errors.h" #include "netty_unix_jni.h" #include "netty_unix_util.h" +#include "netty_jni_util.h" #define ERRORS_CLASSNAME "io/netty/channel/unix/ErrorsStaticallyReferencedJniMethods" @@ -81,7 +82,7 @@ static char* exceptionMessage(char* msg, int error) { } } while (result == ERANGE); - char* combined = netty_unix_util_prepend(msg, strerrbuf); + char* combined = netty_jni_util_prepend(msg, strerrbuf); free(strerrbuf); return combined; } @@ -214,7 +215,7 @@ static const jint statically_referenced_fixed_method_table_size = sizeof(statica jint netty_unix_errors_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { char* nettyClassName = NULL; // We must register the statically referenced methods first! - if (netty_unix_util_register_natives(env, + if (netty_jni_util_register_natives(env, packagePrefix, ERRORS_CLASSNAME, statically_referenced_fixed_method_table, @@ -222,22 +223,22 @@ jint netty_unix_errors_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { return JNI_ERR; } - NETTY_LOAD_CLASS(env, oomErrorClass, "java/lang/OutOfMemoryError", error); + NETTY_JNI_UTIL_LOAD_CLASS(env, oomErrorClass, "java/lang/OutOfMemoryError", error); - NETTY_LOAD_CLASS(env, runtimeExceptionClass, "java/lang/RuntimeException", error); + NETTY_JNI_UTIL_LOAD_CLASS(env, runtimeExceptionClass, "java/lang/RuntimeException", error); - NETTY_PREPEND(packagePrefix, "io/netty/channel/ChannelException", nettyClassName, error); - NETTY_LOAD_CLASS(env, channelExceptionClass, nettyClassName, error); - netty_unix_util_free_dynamic_name(&nettyClassName); + NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/ChannelException", nettyClassName, error); + NETTY_JNI_UTIL_LOAD_CLASS(env, channelExceptionClass, nettyClassName, error); + netty_jni_util_free_dynamic_name(&nettyClassName); - NETTY_LOAD_CLASS(env, closedChannelExceptionClass, "java/nio/channels/ClosedChannelException", error); - NETTY_GET_METHOD(env, closedChannelExceptionClass, closedChannelExceptionMethodId, "", "()V", error); + NETTY_JNI_UTIL_LOAD_CLASS(env, closedChannelExceptionClass, "java/nio/channels/ClosedChannelException", error); + NETTY_JNI_UTIL_GET_METHOD(env, closedChannelExceptionClass, closedChannelExceptionMethodId, "", "()V", error); - NETTY_LOAD_CLASS(env, ioExceptionClass, "java/io/IOException", error); + NETTY_JNI_UTIL_LOAD_CLASS(env, ioExceptionClass, "java/io/IOException", error); - NETTY_LOAD_CLASS(env, portUnreachableExceptionClass, "java/net/PortUnreachableException", error); + NETTY_JNI_UTIL_LOAD_CLASS(env, portUnreachableExceptionClass, "java/net/PortUnreachableException", error); - return NETTY_JNI_VERSION; + return NETTY_JNI_UTIL_JNI_VERSION; error: free(nettyClassName); return JNI_ERR; @@ -245,12 +246,12 @@ error: void netty_unix_errors_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { // delete global references so the GC can collect them - NETTY_UNLOAD_CLASS(env, oomErrorClass); - NETTY_UNLOAD_CLASS(env, runtimeExceptionClass); - NETTY_UNLOAD_CLASS(env, channelExceptionClass); - NETTY_UNLOAD_CLASS(env, ioExceptionClass); - NETTY_UNLOAD_CLASS(env, portUnreachableExceptionClass); - NETTY_UNLOAD_CLASS(env, closedChannelExceptionClass); + NETTY_JNI_UTIL_UNLOAD_CLASS(env, oomErrorClass); + NETTY_JNI_UTIL_UNLOAD_CLASS(env, runtimeExceptionClass); + NETTY_JNI_UTIL_UNLOAD_CLASS(env, channelExceptionClass); + NETTY_JNI_UTIL_UNLOAD_CLASS(env, ioExceptionClass); + NETTY_JNI_UTIL_UNLOAD_CLASS(env, portUnreachableExceptionClass); + NETTY_JNI_UTIL_UNLOAD_CLASS(env, closedChannelExceptionClass); - netty_unix_util_unregister_natives(env, packagePrefix, ERRORS_CLASSNAME); + netty_jni_util_unregister_natives(env, packagePrefix, ERRORS_CLASSNAME); } 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 8b505489eb..d226b7636e 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 @@ -25,6 +25,7 @@ #include "netty_unix_filedescriptor.h" #include "netty_unix_jni.h" #include "netty_unix_util.h" +#include "netty_jni_util.h" #define FILEDESCRIPTOR_CLASSNAME "io/netty/channel/unix/FileDescriptor" @@ -280,7 +281,7 @@ static const jint method_table_size = sizeof(method_table) / sizeof(method_table jint netty_unix_filedescriptor_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { int ret = JNI_ERR; void* mem = NULL; - if (netty_unix_util_register_natives(env, packagePrefix, FILEDESCRIPTOR_CLASSNAME, method_table, method_table_size) != 0) { + if (netty_jni_util_register_natives(env, packagePrefix, FILEDESCRIPTOR_CLASSNAME, method_table, method_table_size) != 0) { goto done; } if ((mem = malloc(1)) == NULL) { @@ -300,21 +301,21 @@ jint netty_unix_filedescriptor_JNI_OnLoad(JNIEnv* env, const char* packagePrefix // Get the method id for Buffer.position() and Buffer.limit(). These are used as fallback if // it is not possible to obtain the position and limit using the fields directly. - NETTY_GET_METHOD(env, cls, posId, "position", "()I", done); - NETTY_GET_METHOD(env, cls, limitId, "limit", "()I", done); + NETTY_JNI_UTIL_GET_METHOD(env, cls, posId, "position", "()I", done); + NETTY_JNI_UTIL_GET_METHOD(env, cls, limitId, "limit", "()I", done); // Try to get the ids of the position and limit fields. We later then check if we was able // to find them and if so use them get the position and limit of the buffer. This is // much faster then call back into java via (*env)->CallIntMethod(...). - NETTY_TRY_GET_FIELD(env, cls, posFieldId, "position", "I"); - NETTY_TRY_GET_FIELD(env, cls, limitFieldId, "limit", "I"); + NETTY_JNI_UTIL_TRY_GET_FIELD(env, cls, posFieldId, "position", "I"); + NETTY_JNI_UTIL_TRY_GET_FIELD(env, cls, limitFieldId, "limit", "I"); - ret = NETTY_JNI_VERSION; + ret = NETTY_JNI_UTIL_JNI_VERSION; done: free(mem); return ret; } void netty_unix_filedescriptor_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { - netty_unix_util_unregister_natives(env, packagePrefix, FILEDESCRIPTOR_CLASSNAME); + netty_jni_util_unregister_natives(env, packagePrefix, FILEDESCRIPTOR_CLASSNAME); } diff --git a/transport-native-unix-common/src/main/c/netty_unix_jni.h b/transport-native-unix-common/src/main/c/netty_unix_jni.h index 6cfe7e3252..2588894299 100644 --- a/transport-native-unix-common/src/main/c/netty_unix_jni.h +++ b/transport-native-unix-common/src/main/c/netty_unix_jni.h @@ -18,8 +18,4 @@ #include -#ifndef NETTY_JNI_VERSION -#define NETTY_JNI_VERSION JNI_VERSION_1_6 -#endif - #endif /* NETTY_UNIX_JNI_H_ */ 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 550f766a15..26756fba94 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 @@ -20,6 +20,7 @@ #include "netty_unix_jni.h" #include "netty_unix_limits.h" #include "netty_unix_util.h" +#include "netty_jni_util.h" #define LIMITS_CLASSNAME "io/netty/channel/unix/LimitsStaticallyReferencedJniMethods" @@ -70,7 +71,7 @@ static const jint statically_referenced_fixed_method_table_size = sizeof(statica jint netty_unix_limits_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { // We must register the statically referenced methods first! - if (netty_unix_util_register_natives(env, + if (netty_jni_util_register_natives(env, packagePrefix, LIMITS_CLASSNAME, statically_referenced_fixed_method_table, @@ -78,9 +79,9 @@ jint netty_unix_limits_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { return JNI_ERR; } - return NETTY_JNI_VERSION; + return NETTY_JNI_UTIL_JNI_VERSION; } void netty_unix_limits_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) { - netty_unix_util_unregister_natives(env, packagePrefix, LIMITS_CLASSNAME); + netty_jni_util_unregister_natives(env, packagePrefix, LIMITS_CLASSNAME); } 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 3725fb626e..da313eb65f 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 @@ -30,6 +30,7 @@ #include "netty_unix_jni.h" #include "netty_unix_socket.h" #include "netty_unix_util.h" +#include "netty_jni_util.h" #define SOCKET_CLASSNAME "io/netty/channel/unix/Socket" // Define SO_REUSEPORT if not found to fix build issues. @@ -1030,23 +1031,23 @@ static JNINativeMethod* createDynamicMethodsTable(const char* packagePrefix) { memcpy(dynamicMethods, fixed_method_table, sizeof(fixed_method_table)); JNINativeMethod* dynamicMethod = &dynamicMethods[fixed_method_table_size]; - NETTY_PREPEND(packagePrefix, "io/netty/channel/unix/DatagramSocketAddress;", dynamicTypeName, error); - NETTY_PREPEND("(ILjava/nio/ByteBuffer;II)L", dynamicTypeName, dynamicMethod->signature, error); + NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/unix/DatagramSocketAddress;", dynamicTypeName, error); + NETTY_JNI_UTIL_PREPEND("(ILjava/nio/ByteBuffer;II)L", dynamicTypeName, dynamicMethod->signature, error); dynamicMethod->name = "recvFrom"; dynamicMethod->fnPtr = (void *) netty_unix_socket_recvFrom; - netty_unix_util_free_dynamic_name(&dynamicTypeName); + netty_jni_util_free_dynamic_name(&dynamicTypeName); ++dynamicMethod; - NETTY_PREPEND(packagePrefix, "io/netty/channel/unix/DatagramSocketAddress;", dynamicTypeName, error); - NETTY_PREPEND("(IJII)L", dynamicTypeName, dynamicMethod->signature, error); + NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/unix/DatagramSocketAddress;", dynamicTypeName, error); + NETTY_JNI_UTIL_PREPEND("(IJII)L", dynamicTypeName, dynamicMethod->signature, error); dynamicMethod->name = "recvFromAddress"; dynamicMethod->fnPtr = (void *) netty_unix_socket_recvFromAddress; - netty_unix_util_free_dynamic_name(&dynamicTypeName); + netty_jni_util_free_dynamic_name(&dynamicTypeName); return dynamicMethods; error: free(dynamicTypeName); - netty_unix_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize()); + netty_jni_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize()); return NULL; } @@ -1060,7 +1061,7 @@ jint netty_unix_socket_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { if (dynamicMethods == NULL) { goto done; } - if (netty_unix_util_register_natives(env, + if (netty_jni_util_register_natives(env, packagePrefix, SOCKET_CLASSNAME, dynamicMethods, @@ -1068,17 +1069,17 @@ jint netty_unix_socket_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { goto done; } - NETTY_PREPEND(packagePrefix, "io/netty/channel/unix/DatagramSocketAddress", nettyClassName, done); - NETTY_LOAD_CLASS(env, datagramSocketAddressClass, nettyClassName, done); + NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/unix/DatagramSocketAddress", nettyClassName, done); + NETTY_JNI_UTIL_LOAD_CLASS(env, datagramSocketAddressClass, nettyClassName, done); // Respect shading... char parameters[1024] = {0}; snprintf(parameters, sizeof(parameters), "([BIIIL%s;)V", nettyClassName); - netty_unix_util_free_dynamic_name(&nettyClassName); - NETTY_GET_METHOD(env, datagramSocketAddressClass, datagramSocketAddrMethodId, "", parameters, done); + netty_jni_util_free_dynamic_name(&nettyClassName); + NETTY_JNI_UTIL_GET_METHOD(env, datagramSocketAddressClass, datagramSocketAddrMethodId, "", parameters, done); - NETTY_LOAD_CLASS(env, inetSocketAddressClass, "java/net/InetSocketAddress", done); - NETTY_GET_METHOD(env, inetSocketAddressClass, inetSocketAddrMethodId, "", "(Ljava/lang/String;I)V", done); + NETTY_JNI_UTIL_LOAD_CLASS(env, inetSocketAddressClass, "java/net/InetSocketAddress", done); + NETTY_JNI_UTIL_GET_METHOD(env, inetSocketAddressClass, inetSocketAddrMethodId, "", "(Ljava/lang/String;I)V", done); if ((mem = malloc(1)) == NULL) { goto done; @@ -1092,17 +1093,17 @@ jint netty_unix_socket_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) { goto done; } - ret = NETTY_JNI_VERSION; + ret = NETTY_JNI_UTIL_JNI_VERSION; done: - netty_unix_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize()); + 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) { - NETTY_UNLOAD_CLASS(env, datagramSocketAddressClass); - NETTY_UNLOAD_CLASS(env, inetSocketAddressClass); + NETTY_JNI_UTIL_UNLOAD_CLASS(env, datagramSocketAddressClass); + NETTY_JNI_UTIL_UNLOAD_CLASS(env, inetSocketAddressClass); - netty_unix_util_unregister_natives(env, packagePrefix, SOCKET_CLASSNAME); + netty_jni_util_unregister_natives(env, packagePrefix, SOCKET_CLASSNAME); } diff --git a/transport-native-unix-common/src/main/c/netty_unix_util.c b/transport-native-unix-common/src/main/c/netty_unix_util.c index fe6f27754a..b9ebbf32a6 100644 --- a/transport-native-unix-common/src/main/c/netty_unix_util.c +++ b/transport-native-unix-common/src/main/c/netty_unix_util.c @@ -28,102 +28,6 @@ static const uint64_t NETTY_BILLION = 1000000000L; #endif /* NETTY_USE_MACH_INSTEAD_OF_CLOCK */ -char* netty_unix_util_prepend(const char* prefix, const char* str) { - if (str == NULL) { - // If str is NULL we should just return NULL as passing NULL to strlen is undefined behavior. - return NULL; - } - char* result = NULL; - if (prefix == NULL) { - if ((result = (char*) malloc(sizeof(char) * (strlen(str) + 1))) == NULL) { - return NULL; - } - strcpy(result, str); - return result; - } - if ((result = (char*) malloc(sizeof(char) * (strlen(prefix) + strlen(str) + 1))) == NULL) { - return NULL; - } - strcpy(result, prefix); - strcat(result, str); - return result; -} - -char* netty_unix_util_rstrstr(char* s1rbegin, const char* s1rend, const char* s2) { - if (s1rbegin == NULL || s1rend == NULL || s2 == NULL) { - // Return NULL if any of the parameters is NULL to not risk a segfault - return NULL; - } - size_t s2len = strlen(s2); - char *s = s1rbegin - s2len; - - for (; s >= s1rend; --s) { - if (strncmp(s, s2, s2len) == 0) { - return s; - } - } - return NULL; -} - -static char* netty_unix_util_strstr_last(const char* haystack, const char* needle) { - if (haystack == NULL || needle == NULL) { - // calling strstr with NULL is undefined behavior. Better just return NULL and not risk a crash. - return NULL; - } - - char* prevptr = NULL; - char* ptr = (char*) haystack; - - while ((ptr = strstr(ptr, needle)) != NULL) { - // Just store the ptr and continue searching. - prevptr = ptr; - ++ptr; - } - return prevptr; -} - -char* netty_unix_util_parse_package_prefix(const char* libraryPathName, const char* libraryName, jint* status) { - char* packageNameEnd = netty_unix_util_strstr_last(libraryPathName, libraryName); - if (packageNameEnd == NULL) { - *status = JNI_ERR; - return NULL; - } - char* packagePrefix = netty_unix_util_rstrstr(packageNameEnd, libraryPathName, "lib"); - if (packagePrefix == NULL) { - *status = JNI_ERR; - return NULL; - } - packagePrefix += 3; - if (packagePrefix == packageNameEnd) { - return NULL; - } - // packagePrefix length is > 0 - // Make a copy so we can modify the value without impacting libraryPathName. - size_t packagePrefixLen = packageNameEnd - packagePrefix; - if ((packagePrefix = strndup(packagePrefix, packagePrefixLen)) == NULL) { - *status = JNI_ERR; - return NULL; - } - // Make sure the packagePrefix is in the correct format for the JNI functions it will be used with. - char* temp = packagePrefix; - packageNameEnd = packagePrefix + packagePrefixLen; - // Package names must be sanitized, in JNI packages names are separated by '/' characters. - for (; temp != packageNameEnd; ++temp) { - if (*temp == '_') { - *temp = '/'; - } - } - // Make sure packagePrefix is terminated with the '/' JNI package separator. - if(*(--temp) != '/') { - temp = packagePrefix; - if ((packagePrefix = netty_unix_util_prepend(packagePrefix, "/")) == NULL) { - *status = JNI_ERR; - } - free(temp); - } - return packagePrefix; -} - // util methods uint64_t netty_unix_util_timespec_elapsed_ns(const struct timespec* begin, const struct timespec* end) { return NETTY_BILLION * (end->tv_sec - begin->tv_sec) + (end->tv_nsec - begin->tv_nsec); @@ -206,52 +110,3 @@ jboolean netty_unix_util_initialize_wait_clock(clockid_t* clockId) { return JNI_FALSE; } - -jint netty_unix_util_register_natives(JNIEnv* env, const char* packagePrefix, const char* className, const JNINativeMethod* methods, jint numMethods) { - char* nettyClassName = NULL; - int ret = JNI_ERR; - NETTY_PREPEND(packagePrefix, className, nettyClassName, done); - - jclass nativeCls = (*env)->FindClass(env, nettyClassName); - if (nativeCls == NULL) { - goto done; - } - - ret = (*env)->RegisterNatives(env, nativeCls, methods, numMethods); -done: - free(nettyClassName); - return ret; -} - -jint netty_unix_util_unregister_natives(JNIEnv* env, const char* packagePrefix, const char* className) { - char* nettyClassName = NULL; - int ret = JNI_ERR; - NETTY_PREPEND(packagePrefix, className, nettyClassName, done); - - jclass nativeCls = (*env)->FindClass(env, nettyClassName); - if (nativeCls == NULL) { - goto done; - } - - ret = (*env)->UnregisterNatives(env, nativeCls); -done: - free(nettyClassName); - return ret; -} - -void netty_unix_util_free_dynamic_methods_table(JNINativeMethod* dynamicMethods, jint fixedMethodTableSize, jint fullMethodTableSize) { - if (dynamicMethods != NULL) { - jint i = fixedMethodTableSize; - for (; i < fullMethodTableSize; ++i) { - free(dynamicMethods[i].signature); - } - free(dynamicMethods); - } -} - -void netty_unix_util_free_dynamic_name(char** dynamicName) { - if (dynamicName != NULL && *dynamicName != NULL) { - free(*dynamicName); - *dynamicName = NULL; - } -} diff --git a/transport-native-unix-common/src/main/c/netty_unix_util.h b/transport-native-unix-common/src/main/c/netty_unix_util.h index 1800919d94..c0529ec05c 100644 --- a/transport-native-unix-common/src/main/c/netty_unix_util.h +++ b/transport-native-unix-common/src/main/c/netty_unix_util.h @@ -20,6 +20,8 @@ #include #include #include +#include "netty_jni_util.h" + #if defined(__MACH__) && !defined(CLOCK_REALTIME) #define NETTY_USE_MACH_INSTEAD_OF_CLOCK @@ -36,87 +38,6 @@ typedef int clockid_t; #endif /* __MACH__ */ - -#define NETTY_BEGIN_MACRO if (1) { -#define NETTY_END_MACRO } else (void)(0) - -#define NETTY_FIND_CLASS(E, C, N, R) \ - NETTY_BEGIN_MACRO \ - C = (*(E))->FindClass((E), N); \ - if (C == NULL) { \ - (*(E))->ExceptionClear((E)); \ - goto R; \ - } \ - NETTY_END_MACRO - -#define NETTY_LOAD_CLASS(E, C, N, R) \ - NETTY_BEGIN_MACRO \ - jclass _##C = (*(E))->FindClass((E), N); \ - if (_##C == NULL) { \ - (*(E))->ExceptionClear((E)); \ - goto R; \ - } \ - C = (*(E))->NewGlobalRef((E), _##C); \ - (*(E))->DeleteLocalRef((E), _##C); \ - if (C == NULL) { \ - goto R; \ - } \ - NETTY_END_MACRO - -#define NETTY_UNLOAD_CLASS(E, C) \ - NETTY_BEGIN_MACRO \ - if (C != NULL) { \ - (*(E))->DeleteGlobalRef((E), (C)); \ - C = NULL; \ - } \ - NETTY_END_MACRO - - -#define NETTY_GET_METHOD(E, C, M, N, S, R) \ - NETTY_BEGIN_MACRO \ - M = (*(E))->GetMethodID((E), C, N, S); \ - if (M == NULL) { \ - goto R; \ - } \ - NETTY_END_MACRO - -#define NETTY_GET_FIELD(E, C, F, N, S, R) \ - NETTY_BEGIN_MACRO \ - F = (*(E))->GetFieldID((E), C, N, S); \ - if (F == NULL) { \ - goto R; \ - } \ - NETTY_END_MACRO - -#define NETTY_TRY_GET_FIELD(E, C, F, N, S) \ - NETTY_BEGIN_MACRO \ - F = (*(E))->GetFieldID((E), C, N, S); \ - if (F == NULL) { \ - (*(E))->ExceptionClear((E)); \ - } \ - NETTY_END_MACRO - -#define NETTY_PREPEND(P, S, N, R) \ - NETTY_BEGIN_MACRO \ - if ((N = netty_unix_util_prepend(P, S)) == NULL) { \ - goto R; \ - } \ - NETTY_END_MACRO -/** - * Return a new string (caller must free this string) which is equivalent to
prefix + str
. - * - * Caller must free the return value! - */ -char* netty_unix_util_prepend(const char* prefix, const char* str); - -char* netty_unix_util_rstrstr(char* s1rbegin, const char* s1rend, const char* s2); - -/** - * The expected format of the library name is "lib<>$libraryName" where the <> portion is what we will return. - * If status != JNI_ERR then the caller MUST call free on the return value. - */ -char* netty_unix_util_parse_package_prefix(const char* libraryPathName, const char* libraryName, jint* status); - /** * Get a clock which can be used to measure execution time. * @@ -145,13 +66,4 @@ uint64_t netty_unix_util_timespec_elapsed_ns(const struct timespec* begin, const */ jboolean netty_unix_util_timespec_subtract_ns(struct timespec* ts, uint64_t nanos); -/** - * Return type is as defined in https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#wp5833. - */ -jint netty_unix_util_register_natives(JNIEnv* env, const char* packagePrefix, const char* className, const JNINativeMethod* methods, jint numMethods); -jint netty_unix_util_unregister_natives(JNIEnv* env, const char* packagePrefix, const char* className); - -void netty_unix_util_free_dynamic_methods_table(JNINativeMethod* dynamicMethods, jint fixedMethodTableSize, jint fullMethodTableSize); -void netty_unix_util_free_dynamic_name(char** dynamicName); - #endif /* NETTY_UNIX_UTIL_H_ */