Make Native loading work better with Java 8

Motivation:
Enable static linking for Java 8.  These commits are the same as those introduced to netty tcnative.  The goal is to allow lots of JNI libraries to be statically linked together without having conflict `JNI_OnLoad` methods.

Modification:
* add JNI_OnLoad suffixes to enable static linking
* Add static names to the list of libraries that try to be loaded
* Enable compiling with JNI 1.8
* Sort includes

Result:
Enable statically linked JNI code.
This commit is contained in:
Carl Mastrangelo 2017-06-21 11:06:08 -07:00 committed by Norman Maurer
parent c3bd1245c5
commit 83de77fbe5
13 changed files with 119 additions and 46 deletions

View File

@ -389,7 +389,7 @@ public final class OpenSsl {
String os = normalizeOs(SystemPropertyUtil.get("os.name", ""));
String arch = normalizeArch(SystemPropertyUtil.get("os.arch", ""));
Set<String> libNames = new LinkedHashSet<String>(3);
Set<String> libNames = new LinkedHashSet<String>(4);
// First, try loading the platform-specific library. Platform-specific
// libraries will be available if using a tcnative uber jar.
libNames.add("netty-tcnative-" + os + '-' + arch);
@ -399,6 +399,8 @@ public final class OpenSsl {
}
// finally the default library.
libNames.add("netty-tcnative");
// in Java 8, statically compiled JNI code is namespaced
libNames.add("netty_tcnative");
NativeLibraryLoader.loadFirstAvailable(SSL.class.getClassLoader(),
libNames.toArray(new String[libNames.size()]));

View File

@ -26,11 +26,13 @@
#include <errno.h>
#include <netinet/in.h>
#include <linux/tcp.h> // TCP_NOTSENT_LOWAT is a linux specific define
#include "netty_unix_filedescriptor.h"
#include "netty_unix_socket.h"
#include "netty_unix_errors.h"
#include "netty_unix_util.h"
#include "netty_epoll_linuxsocket.h"
#include "netty_unix_errors.h"
#include "netty_unix_filedescriptor.h"
#include "netty_unix_jni.h"
#include "netty_unix_socket.h"
#include "netty_unix_util.h"
// TCP_FASTOPEN is defined in linux 3.7. We define this here so older kernels can compile.
#ifndef TCP_FASTOPEN
@ -349,7 +351,7 @@ jint netty_epoll_linuxsocket_JNI_OnLoad(JNIEnv* env, const char* packagePrefix)
return JNI_ERR;
}
return JNI_VERSION_1_6;
return NETTY_JNI_VERSION;
}
void netty_epoll_linuxsocket_JNI_OnUnLoad(JNIEnv* env) {

View File

@ -36,12 +36,14 @@
#include <inttypes.h>
#include <link.h>
#include <time.h>
#include "netty_unix_filedescriptor.h"
#include "netty_unix_socket.h"
#include "netty_unix_errors.h"
#include "netty_unix_util.h"
#include "netty_unix_limits.h"
#include "netty_epoll_linuxsocket.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"
// TCP_FASTOPEN is defined in linux 3.7. We define this here so older kernels can compile.
#ifndef TCP_FASTOPEN
@ -575,7 +577,7 @@ static jint netty_epoll_native_JNI_OnLoad(JNIEnv* env, const char* packagePrefix
return JNI_ERR;
}
return JNI_VERSION_1_6;
return NETTY_JNI_VERSION;
}
static void netty_epoll_native_JNI_OnUnLoad(JNIEnv* env) {
@ -586,12 +588,14 @@ static void netty_epoll_native_JNI_OnUnLoad(JNIEnv* env) {
netty_epoll_linuxsocket_JNI_OnUnLoad(env);
}
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
// Invoked by the JVM when statically linked
jint JNI_OnLoad_netty_transport_native_epoll(JavaVM* vm, void* reserved) {
JNIEnv* env;
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_6) != JNI_OK) {
if ((*vm)->GetEnv(vm, (void**) &env, NETTY_JNI_VERSION) != JNI_OK) {
return JNI_ERR;
}
char* packagePrefix = NULL;
#ifndef NETTY_NOT_DYNAMIC
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
@ -600,12 +604,12 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
fprintf(stderr, "FATAL: transport-native-epoll JNI call to dladdr failed!\n");
return JNI_ERR;
}
char* packagePrefix = netty_unix_util_parse_package_prefix(dlinfo.dli_fname, "netty-transport-native-epoll", &status);
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_NOT_DYNAMIC */
jint ret = netty_epoll_native_JNI_OnLoad(env, packagePrefix);
if (packagePrefix != NULL) {
@ -616,11 +620,20 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
return ret;
}
void JNI_OnUnload(JavaVM* vm, void* reserved) {
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
return JNI_OnLoad_netty_transport_native_epoll(vm, reserved);
}
// Invoked by the JVM when statically linked
void JNI_OnUnload_netty_transport_native_epoll(JavaVM* vm, void* reserved) {
JNIEnv* env;
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_6) != JNI_OK) {
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);
}
void JNI_OnUnload(JavaVM* vm, void* reserved) {
JNI_OnUnload_netty_transport_native_epoll(vm, reserved);
}

View File

@ -188,7 +188,11 @@ public final class Native {
if (!name.startsWith("linux")) {
throw new IllegalStateException("Only supported on Linux");
}
NativeLibraryLoader.load("netty-transport-native-epoll", PlatformDependent.getClassLoader(Native.class));
String []libraryNames = new String[] {
"netty-transport-native-epoll",
"netty_transport_native_epoll"
};
NativeLibraryLoader.loadFirstAvailable(PlatformDependent.getClassLoader(Native.class), libraryNames);
}
private Native() {

View File

@ -24,11 +24,13 @@
#include <sys/ucred.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include "netty_unix_filedescriptor.h"
#include "netty_unix_socket.h"
#include "netty_unix_errors.h"
#include "netty_unix_util.h"
#include "netty_kqueue_bsdsocket.h"
#include "netty_unix_errors.h"
#include "netty_unix_filedescriptor.h"
#include "netty_unix_jni.h"
#include "netty_unix_socket.h"
#include "netty_unix_util.h"
// Those are initialized in the init(...) method and cached for performance reasons
static jclass stringCls = NULL;
@ -288,7 +290,7 @@ jint netty_kqueue_bsdsocket_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
return JNI_ERR;
}
return JNI_VERSION_1_6;
return NETTY_JNI_VERSION;
}
void netty_kqueue_bsdsocket_JNI_OnUnLoad(JNIEnv* env) {

View File

@ -18,9 +18,11 @@
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include "netty_unix_util.h"
#include "netty_unix_errors.h"
#include "netty_kqueue_eventarray.h"
#include "netty_unix_errors.h"
#include "netty_unix_jni.h"
#include "netty_unix_util.h"
jfieldID kqueueJniPtrFieldId = NULL;
@ -117,7 +119,7 @@ jint netty_kqueue_eventarray_JNI_OnLoad(JNIEnv* env, const char* packagePrefix)
return JNI_ERR;
}
return JNI_VERSION_1_6;
return NETTY_JNI_VERSION;
}
void netty_kqueue_eventarray_JNI_OnUnLoad(JNIEnv* env) {

View File

@ -25,13 +25,16 @@
#include <sys/event.h>
#include <sys/socket.h>
#include <sys/time.h>
#include "netty_unix_filedescriptor.h"
#include "netty_unix_socket.h"
#include "netty_unix_errors.h"
#include "netty_unix_util.h"
#include "netty_unix_limits.h"
#include "netty_kqueue_bsdsocket.h"
#include "netty_kqueue_eventarray.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"
clockid_t waitClockId = 0; // initialized by netty_unix_util_initialize_wait_clock
@ -255,7 +258,7 @@ static jint netty_kqueue_native_JNI_OnLoad(JNIEnv* env, const char* packagePrefi
return JNI_ERR;
}
return JNI_VERSION_1_6;
return NETTY_JNI_VERSION;
}
static void netty_kqueue_native_JNI_OnUnLoad(JNIEnv* env) {
@ -267,12 +270,15 @@ static void netty_kqueue_native_JNI_OnUnLoad(JNIEnv* env) {
netty_kqueue_eventarray_JNI_OnUnLoad(env);
}
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
// Invoked by the JVM when statically linked
jint JNI_OnLoad_netty_transport_native_kqueue(JavaVM* vm, void* reserved) {
JNIEnv* env;
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_6) != JNI_OK) {
if ((*vm)->GetEnv(vm, (void**) &env, NETTY_JNI_VERSION) != JNI_OK) {
return JNI_ERR;
}
char* packagePrefix = NULL;
#ifndef NETTY_NOT_DYNAMIC
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
@ -281,12 +287,12 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
fprintf(stderr, "FATAL: transport-native-kqueue JNI call to dladdr failed!\n");
return JNI_ERR;
}
char* packagePrefix = netty_unix_util_parse_package_prefix(dlinfo.dli_fname, "netty-transport-native-kqueue", &status);
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_NOT_DYNAMIC */
jint ret = netty_kqueue_native_JNI_OnLoad(env, packagePrefix);
if (packagePrefix != NULL) {
@ -297,11 +303,20 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
return ret;
}
void JNI_OnUnload(JavaVM* vm, void* reserved) {
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
return JNI_OnLoad_netty_transport_native_kqueue(vm, reserved);
}
// Invoked by the JVM when statically linked
void JNI_OnUnload_netty_transport_native_kqueue(JavaVM* vm, void* reserved) {
JNIEnv* env;
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_6) != JNI_OK) {
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);
}
void JNI_OnUnload(JavaVM* vm, void* reserved) {
return JNI_OnUnload_netty_transport_native_kqueue(vm, reserved);
}

View File

@ -100,7 +100,11 @@ final class Native {
if (!name.startsWith("mac") && !name.contains("bsd") && !name.startsWith("darwin")) {
throw new IllegalStateException("Only supported on BSD");
}
NativeLibraryLoader.load("netty-transport-native-kqueue", PlatformDependent.getClassLoader(Native.class));
String []libraryNames = new String[] {
"netty-transport-native-kqueue",
"netty_transport_native_kqueue"
};
NativeLibraryLoader.loadFirstAvailable(PlatformDependent.getClassLoader(Native.class), libraryNames);
}
private Native() {

View File

@ -18,6 +18,7 @@
#include <errno.h>
#include <jni.h>
#include "netty_unix_errors.h"
#include "netty_unix_jni.h"
#include "netty_unix_util.h"
static jclass runtimeExceptionClass = NULL;
@ -206,7 +207,7 @@ jint netty_unix_errors_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
return JNI_ERR;
}
return JNI_VERSION_1_6;
return NETTY_JNI_VERSION;
}
void netty_unix_errors_JNI_OnUnLoad(JNIEnv* env) {

View File

@ -20,9 +20,10 @@
#include <unistd.h>
#include <sys/uio.h>
#include "netty_unix_util.h"
#include "netty_unix_errors.h"
#include "netty_unix_filedescriptor.h"
#include "netty_unix_jni.h"
#include "netty_unix_util.h"
static jmethodID posId = NULL;
static jmethodID limitId = NULL;
@ -261,7 +262,7 @@ jint netty_unix_filedescriptor_JNI_OnLoad(JNIEnv* env, const char* packagePrefix
}
free(mem);
return JNI_VERSION_1_6;
return NETTY_JNI_VERSION;
}
void netty_unix_filedescriptor_JNI_OnUnLoad(JNIEnv* env) { }

View File

@ -0,0 +1,25 @@
/*
* Copyright 2017 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:
*
* http://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_JNI_H_
#define NETTY_UNIX_JNI_H_
#include <jni.h>
#ifndef NETTY_JNI_VERSION
#define NETTY_JNI_VERSION JNI_VERSION_1_6
#endif
#endif /* NETTY_UNIX_JNI_H_ */

View File

@ -17,6 +17,7 @@
#include <stdio.h>
#include <sys/types.h>
#include <sys/un.h>
#include "netty_unix_jni.h"
#include "netty_unix_limits.h"
#include "netty_unix_util.h"
@ -75,7 +76,7 @@ jint netty_unix_limits_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
return JNI_ERR;
}
return JNI_VERSION_1_6;
return NETTY_JNI_VERSION;
}
void netty_unix_limits_JNI_OnUnLoad(JNIEnv* env) { }

View File

@ -26,6 +26,7 @@
#include <netinet/tcp.h>
#include "netty_unix_errors.h"
#include "netty_unix_jni.h"
#include "netty_unix_socket.h"
#include "netty_unix_util.h"
@ -974,7 +975,7 @@ jint netty_unix_socket_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
free(mem);
socketType = socket_type(env);
return JNI_VERSION_1_6;
return NETTY_JNI_VERSION;
}
void netty_unix_socket_JNI_OnUnLoad(JNIEnv* env) {