Skip to content

Commit

Permalink
Automatically detect shaded packagePrefix
Browse files Browse the repository at this point in the history
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 netty#6963
  • Loading branch information
ejona86 authored and Scottmitch committed Jul 20, 2017
1 parent 3d22b24 commit e5a31a4
Showing 1 changed file with 21 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,32 @@ public static void loadFirstAvailable(ClassLoader loader, String... 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}
*/
public static void load(String originalName, ClassLoader loader) {
// 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 path = NATIVE_RESOURCE_HOME + libname;
Expand Down

0 comments on commit e5a31a4

Please sign in to comment.