Ensure multiple shaded version of the same netty artifact can be loaded as long as the shaded prefix is different (#8207)

Motivation:

We should support to load multiple shaded versions of the same netty artifact as netty is often used in multiple dependencies.

This is related to https://github.com/netty/netty/issues/7272.

Modifications:

- Use -fvisibility=hidden when compiling and use JNIEXPORT for things we really want to have exported
- Ensure fields are declared as static so these are not exported
- Adjust testsuite-shading to use install_name_tool on MacOS to change the id of the lib. Otherwise the wrong may be used.

Result:

Be able to use multiple shaded versions of the same netty artifact.
This commit is contained in:
Norman Maurer 2018-08-21 07:53:45 +02:00 committed by GitHub
parent 182ffdaf6d
commit ea4c315b45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 149 additions and 43 deletions

View File

@ -34,6 +34,8 @@
<classesShadedDir>${project.build.directory}/classes-shaded</classesShadedDir>
<classesShadedNativeDir>${classesShadedDir}/META-INF/native</classesShadedNativeDir>
<shadingPrefix>shaded</shadingPrefix>
<shadingPrefix2>shaded2</shadingPrefix2>
<jarName>${project.artifactId}-${project.version}.jar</jarName>
<shadedPackagePrefix>io.netty.</shadedPackagePrefix>
</properties>
@ -104,6 +106,7 @@
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<id>shade</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
@ -122,6 +125,26 @@
</relocations>
</configuration>
</execution>
<execution>
<id>shade-1</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>${project.groupId}</include>
</includes>
</artifactSet>
<relocations>
<relocation>
<pattern>${shadedPackagePrefix}</pattern>
<shadedPattern>${shadingPrefix2}.${shadedPackagePrefix}</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
@ -141,8 +164,36 @@
<include name="${jarName}" />
</fileset>
</unzip>
<move file="${classesShadedNativeDir}/lib${nativeTransportLib}" tofile="${classesShadedNativeDir}/lib${shadingPrefix}_${nativeTransportLib}" />
<move file="${classesShadedNativeDir}/lib${nativeTcnativeLib}" tofile="${classesShadedNativeDir}/lib${shadingPrefix}_${nativeTcnativeLib}" />
<copy file="${classesShadedNativeDir}/lib${nativeTransportLib}" tofile="${classesShadedNativeDir}/lib${shadingPrefix}_${nativeTransportLib}" />
<copy file="${classesShadedNativeDir}/lib${nativeTransportLib}" tofile="${classesShadedNativeDir}/lib${shadingPrefix2}_${nativeTransportLib}" />
<exec executable="install_name_tool" failonerror="true" dir="${project.build.directory}/" resolveexecutable="true">
<arg value="-id" />
<arg value="lib${shadingPrefix}_${nativeTransportLib}" />
<arg value="${classesShadedNativeDir}/lib${shadingPrefix}_${nativeTransportLib}" />
</exec>
<!-- We need to adjust the ID used on MacOS so we are sure the correct lib is loaded later on -->
<exec executable="install_name_tool" failonerror="true" dir="${project.build.directory}/" resolveexecutable="true">
<arg value="-id" />
<arg value="lib${shadingPrefix2}_${nativeTransportLib}" />
<arg value="${classesShadedNativeDir}/lib${shadingPrefix2}_${nativeTransportLib}" />
</exec>
<delete file="${classesShadedNativeDir}/lib${nativeTransportLib}" />
<copy file="${classesShadedNativeDir}/lib${nativeTcnativeLib}" tofile="${classesShadedNativeDir}/lib${shadingPrefix}_${nativeTcnativeLib}" />
<copy file="${classesShadedNativeDir}/lib${nativeTcnativeLib}" tofile="${classesShadedNativeDir}/lib${shadingPrefix2}_${nativeTcnativeLib}" />
<exec executable="install_name_tool" failonerror="true" dir="${project.build.directory}/" resolveexecutable="true">
<arg value="-id" />
<arg value="lib${shadingPrefix}_${nativeTcnativeLib}" />
<arg value="${classesShadedNativeDir}/lib${shadingPrefix}_${nativeTcnativeLib}" />
</exec>
<!-- We need to adjust the ID used on MacOS so we are sure the correct lib is loaded later on -->
<exec executable="install_name_tool" failonerror="true" dir="${project.build.directory}/" resolveexecutable="true">
<arg value="-id" />
<arg value="lib${shadingPrefix2}_${nativeTcnativeLib}" />
<arg value="${classesShadedNativeDir}/lib${shadingPrefix2}_${nativeTcnativeLib}" />
</exec>
<delete file="${classesShadedNativeDir}/lib${nativeTcnativeLib}" />
<jar destfile="${project.build.directory}/${jarName}" basedir="${classesShadedDir}" />
<delete dir="${classesShadedDir}" />
</target>
@ -156,6 +207,7 @@
<configuration>
<systemPropertyVariables>
<shadingPrefix>${shadingPrefix}</shadingPrefix>
<shadingPrefix2>${shadingPrefix2}</shadingPrefix2>
</systemPropertyVariables>
</configuration>
<executions>
@ -211,6 +263,7 @@
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<id>shade</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
@ -229,6 +282,26 @@
</relocations>
</configuration>
</execution>
<execution>
<id>shade-1</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>${project.groupId}</include>
</includes>
</artifactSet>
<relocations>
<relocation>
<pattern>${shadedPackagePrefix}</pattern>
<shadedPattern>${shadingPrefix2}.${shadedPackagePrefix}</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
@ -248,8 +321,14 @@
<include name="${jarName}" />
</fileset>
</unzip>
<move file="${classesShadedNativeDir}/lib${nativeTransportLib}" tofile="${classesShadedNativeDir}/lib${shadingPrefix}_${nativeTransportLib}" />
<move file="${classesShadedNativeDir}/lib${nativeTcnativeLib}" tofile="${classesShadedNativeDir}/lib${shadingPrefix}_${nativeTcnativeLib}" />
<copy file="${classesShadedNativeDir}/lib${nativeTransportLib}" tofile="${classesShadedNativeDir}/lib${shadingPrefix}_${nativeTransportLib}" />
<copy file="${classesShadedNativeDir}/lib${nativeTransportLib}" tofile="${classesShadedNativeDir}/lib${shadingPrefix2}_${nativeTransportLib}" />
<delete file="${classesShadedNativeDir}/lib${nativeTransportLib}" />
<copy file="${classesShadedNativeDir}/lib${nativeTcnativeLib}" tofile="${classesShadedNativeDir}/lib${shadingPrefix}_${nativeTcnativeLib}" />
<copy file="${classesShadedNativeDir}/lib${nativeTcnativeLib}" tofile="${classesShadedNativeDir}/lib${shadingPrefix2}_${nativeTcnativeLib}" />
<delete file="${classesShadedNativeDir}/lib${nativeTcnativeLib}" />
<jar destfile="${project.build.directory}/${jarName}" basedir="${classesShadedDir}" />
<delete dir="${classesShadedDir}" />
</target>
@ -263,6 +342,7 @@
<configuration>
<systemPropertyVariables>
<shadingPrefix>${shadingPrefix}</shadingPrefix>
<shadingPrefix2>${shadingPrefix2}</shadingPrefix2>
</systemPropertyVariables>
</configuration>
<executions>

View File

@ -23,19 +23,26 @@ import java.lang.reflect.Method;
public class ShadingIT {
private static final String SHADING_PREFIX = System.getProperty("shadingPrefix2");
private static final String SHADING_PREFIX2 = System.getProperty("shadingPrefix");
@Test
public void testShadingNativeTransport() throws Exception {
testShading0(PlatformDependent.isOsx() ? "io.netty.channel.kqueue.KQueue" : "io.netty.channel.epoll.Epoll");
String className = PlatformDependent.isOsx() ?
"io.netty.channel.kqueue.KQueue" : "io.netty.channel.epoll.Epoll";
testShading0(SHADING_PREFIX, className);
testShading0(SHADING_PREFIX2, className);
}
@Ignore("Figure out why this sometimes fail on the CI")
@Test
public void testShadingTcnative() throws Exception {
testShading0("io.netty.handler.ssl.OpenSsl");
String className = "io.netty.handler.ssl.OpenSsl";
testShading0(SHADING_PREFIX, className);
testShading0(SHADING_PREFIX2, className);
}
private static void testShading0(String classname) throws Exception {
String shadingPrefix = System.getProperty("shadingPrefix");
private static void testShading0(String shadingPrefix, String classname) throws Exception {
final Class<?> clazz = Class.forName(shadingPrefix + '.' + classname);
Method method = clazz.getMethod("ensureAvailability");
method.invoke(null);

View File

@ -265,7 +265,7 @@
<value>${linux.sendmmsg.support}${glibc.sendmmsg.support}</value>
<!-- If glibc and linux kernel are both not sufficient...then define the CFLAGS -->
<regex>.*IO_NETTY_SENDMSSG_NOT_FOUND.*</regex>
<replacement>CFLAGS=-O3 -DIO_NETTY_SENDMMSG_NOT_FOUND -Werror -fno-omit-frame-pointer -Wunused-variable -I${unix.common.include.unpacked.dir}</replacement>
<replacement>CFLAGS=-O3 -DIO_NETTY_SENDMMSG_NOT_FOUND -Werror -fno-omit-frame-pointer -Wunused-variable -fvisibility=hidden -I${unix.common.include.unpacked.dir}</replacement>
<failIfNoMatch>false</failIfNoMatch>
</configuration>
</execution>
@ -281,7 +281,7 @@
<value>${jni.compiler.args.cflags}</value>
<!-- If glibc and linux kernel are both not sufficient...then define the CFLAGS -->
<regex>^((?!CFLAGS=).)*$</regex>
<replacement>CFLAGS=-O3 -Werror -fno-omit-frame-pointer -Wunused-variable -I${unix.common.include.unpacked.dir}</replacement>
<replacement>CFLAGS=-O3 -Werror -fno-omit-frame-pointer -Wunused-variable -fvisibility=hidden -I${unix.common.include.unpacked.dir}</replacement>
<failIfNoMatch>false</failIfNoMatch>
</configuration>
</execution>

View File

@ -65,11 +65,11 @@ struct mmsghdr {
#endif
// Those are initialized in the init(...) method and cached for performance reasons
jfieldID packetAddrFieldId = NULL;
jfieldID packetScopeIdFieldId = NULL;
jfieldID packetPortFieldId = NULL;
jfieldID packetMemoryAddressFieldId = NULL;
jfieldID packetCountFieldId = NULL;
static jfieldID packetAddrFieldId = NULL;
static jfieldID packetScopeIdFieldId = NULL;
static jfieldID packetPortFieldId = NULL;
static jfieldID packetMemoryAddressFieldId = NULL;
static jfieldID packetCountFieldId = NULL;
// util methods
static int getSysctlValue(const char * property, int* returnValue) {
@ -505,7 +505,7 @@ static void netty_epoll_native_JNI_OnUnLoad(JNIEnv* env) {
}
// Invoked by the JVM when statically linked
jint JNI_OnLoad_netty_transport_native_epoll(JavaVM* vm, void* reserved) {
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;
@ -536,14 +536,7 @@ jint JNI_OnLoad_netty_transport_native_epoll(JavaVM* vm, void* reserved) {
return ret;
}
#ifndef NETTY_BUILD_STATIC
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
return JNI_OnLoad_netty_transport_native_epoll(vm, reserved);
}
#endif /* NETTY_BUILD_STATIC */
// Invoked by the JVM when statically linked
void JNI_OnUnload_netty_transport_native_epoll(JavaVM* vm, void* reserved) {
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 :(
@ -552,8 +545,25 @@ void JNI_OnUnload_netty_transport_native_epoll(JavaVM* vm, void* reserved) {
netty_epoll_native_JNI_OnUnLoad(env);
}
// We build with -fvisibility=hidden so ensure we mark everything that needs to be visible with JNIEXPORT
// http://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);
}
// 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);
}
#ifndef NETTY_BUILD_STATIC
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
return JNI_OnLoad_netty_transport_native_epoll0(vm, reserved);
}
JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved) {
JNI_OnUnload_netty_transport_native_epoll(vm, reserved);
JNI_OnUnload_netty_transport_native_epoll0(vm, reserved);
}
#endif /* NETTY_BUILD_STATIC */

View File

@ -361,7 +361,7 @@
<unix.common.lib.dir>${project.build.directory}/unix-common-lib</unix.common.lib.dir>
<unix.common.lib.unpacked.dir>${unix.common.lib.dir}/META-INF/native/lib</unix.common.lib.unpacked.dir>
<unix.common.include.unpacked.dir>${unix.common.lib.dir}/META-INF/native/include</unix.common.include.unpacked.dir>
<jni.compiler.args.cflags>CFLAGS=-O3 -Werror -fno-omit-frame-pointer -Wunused-variable -I${unix.common.include.unpacked.dir}</jni.compiler.args.cflags>
<jni.compiler.args.cflags>CFLAGS=-O3 -Werror -fno-omit-frame-pointer -Wunused-variable -fvisibility=hidden -I${unix.common.include.unpacked.dir}</jni.compiler.args.cflags>
<jni.compiler.args.ldflags>LDFLAGS=-z now -L${unix.common.lib.unpacked.dir} -Wl,--whole-archive -l${unix.common.lib.name} -Wl,--no-whole-archive</jni.compiler.args.ldflags>
<skipTests>true</skipTests>
</properties>

View File

@ -24,7 +24,7 @@
#include "netty_unix_jni.h"
#include "netty_unix_util.h"
jfieldID kqueueJniPtrFieldId = NULL;
static jfieldID kqueueJniPtrFieldId = NULL;
static void netty_kqueue_eventarray_evSet(JNIEnv* env, jclass clzz, jlong keventAddress, jobject channel, jint ident, jshort filter, jshort flags, jint fflags) {
// Create a global pointer, cast it as a long, and retain it in java to re-use and free later.

View File

@ -65,7 +65,7 @@
#endif /* NOTE_DISCONNECTED */
#endif /* __APPLE__ */
clockid_t waitClockId = 0; // initialized by netty_unix_util_initialize_wait_clock
static clockid_t waitClockId = 0; // initialized by netty_unix_util_initialize_wait_clock
static jint netty_kqueue_native_kqueueCreate(JNIEnv* env, jclass clazz) {
jint kq = kqueue();
@ -318,8 +318,7 @@ static void netty_kqueue_native_JNI_OnUnLoad(JNIEnv* env) {
netty_kqueue_eventarray_JNI_OnUnLoad(env);
}
// Invoked by the JVM when statically linked
jint JNI_OnLoad_netty_transport_native_kqueue(JavaVM* vm, void* reserved) {
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;
@ -351,14 +350,7 @@ jint JNI_OnLoad_netty_transport_native_kqueue(JavaVM* vm, void* reserved) {
return ret;
}
#ifndef NETTY_BUILD_STATIC
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
return JNI_OnLoad_netty_transport_native_kqueue(vm, reserved);
}
#endif /* NETTY_BUILD_STATIC */
// Invoked by the JVM when statically linked
void JNI_OnUnload_netty_transport_native_kqueue(JavaVM* vm, void* reserved) {
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 :(
@ -367,8 +359,25 @@ void JNI_OnUnload_netty_transport_native_kqueue(JavaVM* vm, void* reserved) {
netty_kqueue_native_JNI_OnUnLoad(env);
}
// We build with -fvisibility=hidden so ensure we mark everything that needs to be visible with JNIEXPORT
// http://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_kqueue(JavaVM* vm, void* reserved) {
return JNI_OnLoad_netty_transport_native_kqueue0(vm, reserved);
}
// 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);
}
#ifndef NETTY_BUILD_STATIC
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
return JNI_OnLoad_netty_transport_native_kqueue0(vm, reserved);
}
JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved) {
return JNI_OnUnload_netty_transport_native_kqueue(vm, reserved);
return JNI_OnUnload_netty_transport_native_kqueue0(vm, reserved);
}
#endif /* NETTY_BUILD_STATIC */

View File

@ -101,7 +101,7 @@
<env key="LIB_DIR" value="${nativeLibOnlyDir}" />
<env key="OBJ_DIR" value="${nativeObjsOnlyDir}" />
<env key="JNI_PLATFORM" value="${jni.platform}" />
<env key="CFLAGS" value="-O3 -Werror -Wno-attributes -fPIC -fno-omit-frame-pointer -Wunused-variable" />
<env key="CFLAGS" value="-O3 -Werror -Wno-attributes -fPIC -fno-omit-frame-pointer -Wunused-variable -fvisibility=hidden" />
<env key="LDFLAGS" value="-Wl,--no-as-needed -lrt" />
<env key="LIB_NAME" value="${nativeLibName}" />
<!-- support for __attribute__((weak_import)) by the linker was added in 10.2 so ensure we
@ -172,7 +172,7 @@
<env key="LIB_DIR" value="${nativeLibOnlyDir}" />
<env key="OBJ_DIR" value="${nativeObjsOnlyDir}" />
<env key="JNI_PLATFORM" value="${jni.platform}" />
<env key="CFLAGS" value="-O3 -Werror -Wno-attributes -fPIC -fno-omit-frame-pointer -Wunused-variable" />
<env key="CFLAGS" value="-O3 -Werror -Wno-attributes -fPIC -fno-omit-frame-pointer -Wunused-variable -fvisibility=hidden" />
<env key="LDFLAGS" value="-Wl,--no-as-needed -lrt" />
<env key="LIB_NAME" value="${nativeLibName}" />
</exec>
@ -242,7 +242,7 @@
<env key="LIB_DIR" value="${nativeLibOnlyDir}" />
<env key="OBJ_DIR" value="${nativeObjsOnlyDir}" />
<env key="JNI_PLATFORM" value="${jni.platform}" />
<env key="CFLAGS" value="-O3 -Werror -Wno-attributes -fPIC -fno-omit-frame-pointer -Wunused-variable" />
<env key="CFLAGS" value="-O3 -Werror -Wno-attributes -fPIC -fno-omit-frame-pointer -Wunused-variable -fvisibility=hidden" />
<env key="LDFLAGS" value="-Wl,--no-as-needed -lrt" />
<env key="LIB_NAME" value="${nativeLibName}" />
</exec>
@ -312,7 +312,7 @@
<env key="LIB_DIR" value="${nativeLibOnlyDir}" />
<env key="OBJ_DIR" value="${nativeObjsOnlyDir}" />
<env key="JNI_PLATFORM" value="${jni.platform}" />
<env key="CFLAGS" value="-O3 -Werror -Wno-attributes -fPIC -fno-omit-frame-pointer -Wunused-variable" />
<env key="CFLAGS" value="-O3 -Werror -Wno-attributes -fPIC -fno-omit-frame-pointer -Wunused-variable -fvisibility=hidden" />
<env key="LDFLAGS" value="-Wl,--no-as-needed -lrt" />
<env key="LIB_NAME" value="${nativeLibName}" />
</exec>