Automatically detect shaded packagePrefix

Motivation:

Shading requires renaming binary components (.so, .dll; for tcnative,
epoll, etc). But the rename then requires setting the
io.netty.packagePrefix system property on the command line or runtime,
which is either a burden or not feasible.

If you don't rename the binary components everything appears to
work, until a dependency on a second version of the binary component is
added. At that point, only one version of the binary will be loaded...
which is what shading is supposed to prevent. So for valid shading, the
binaries must be renamed.

Modifications:

Automatically detect the package prefix by comparing the actual class
name to the non-shaded expected class name. The expected class name must
be obfuscated to prevent shading utilities from changing it.

Result:

When shading and using binary components, runtime configuration is no
longer necessary.

Pre-existing shading users that were not renaming the binary components
will break, because the packagePrefix previously defaulted to "". Since
these pre-existing users had broken configurations that only _appeared_
to work, this breakage is considered a Good Thing. Users may workaround
this breakage temporarily by setting -Dio.netty.packagePrefix= to
restore packagePrefix to "".

Fixes #6963
This commit is contained in:
Eric Anderson 2017-07-19 15:50:38 -07:00 committed by Scott Mitchell
parent 3d22b24244
commit e5a31a4282

View File

@ -180,12 +180,32 @@ public final class NativeLibraryLoader {
+ Arrays.toString(names)); + Arrays.toString(names));
} }
/**
* The shading prefix added to this class's full name.
*
* @throws UnsatisfiedLinkError if the shader used something other than a prefix
*/
private static String calculatePackagePrefix() {
String maybeShaded = NativeLibraryLoader.class.getName();
// Use ! instead of . to avoid shading utilities from modifying the string
String expected = "io!netty!util!internal!NativeLibraryLoader".replace('!', '.');
if (!maybeShaded.endsWith(expected)) {
throw new UnsatisfiedLinkError(String.format(
"Could not find prefix added to %s to get %s. When shading, only adding a "
+ "package prefix is supported", expected, maybeShaded));
}
return maybeShaded.substring(0, maybeShaded.length() - expected.length());
}
/** /**
* Load the given library with the specified {@link ClassLoader} * Load the given library with the specified {@link ClassLoader}
*/ */
public static void load(String originalName, ClassLoader loader) { public static void load(String originalName, ClassLoader loader) {
// Adjust expected name to support shading of native libraries. // Adjust expected name to support shading of native libraries.
String name = SystemPropertyUtil.get("io.netty.packagePrefix", "").replace('.', '-') + originalName; String implicitPackagePrefix = calculatePackagePrefix();
// The system property should not be necessary; it can be removed in the future.
String packagePrefix = SystemPropertyUtil.get("io.netty.packagePrefix", implicitPackagePrefix);
String name = packagePrefix.replace('.', '-') + originalName;
String libname = System.mapLibraryName(name); String libname = System.mapLibraryName(name);
String path = NATIVE_RESOURCE_HOME + libname; String path = NATIVE_RESOURCE_HOME + libname;