-Dio.netty.packagePrefix should not be required when shading
See original GitHub issueExpected behavior
A library may use shading transparently to the user and would be able to be combined with other libraries that also use Netty. Similarly, an application should be able to use shading transparently to the user.
Actual behavior
The shader has to choose whether to rename the native components of epoll and tcnative. If they are renamed, then -Dio.netty.packagePrefix
must be set at runtime, which may not be possible programatically. If they aren’t renamed, then epoll and tcnative can fail when mixed with other libraries because: 1) there is a name collision of the META-INF/native/
files in the class path and 2) System.loadLibrary(String)
does nothing if it previously loaded a particular name.
Possible fixes
NativeLibraryLoader
currently defaults to a package prefix of ""
:
String name = SystemPropertyUtil.get("io.netty.packagePrefix", "").replace('.', '-') + originalName;
Instead of defaulting to ""
, I think it should at least attempt to find a package prefix from the class path. There are many options. A sampling:
// Semi-readable implicit
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)) {
return maybeShaded.substring(0, maybeShaded.length() - expected.size());
} else {
throw ...;
}
// Quick and dirty implicit
String name = NativeLibraryLoader.class.getName();
// 42 == "io.netty.util.internal.NativeLibraryLoader".length()
return name.substring(0, name.length() - 42);
// Pre-configured (explicit). User created a file for Netty to read
String resourceName = obfuscateConcat("/META-INF/native/", "io.netty.packagePrefix");
// Could also be a relative, but then users would need to create a file in
// io/netty/util/internal or similar subpackage (I don't see any class in
// io.netty package).
// String resourceName = "packagePrefix";
InputStream is = NativeLibraryLoader.class.getResourceAsStream(resourceName);
if (is == null) {
return "";
}
return asStringUtf8(is);
In my mind, when shaded, a ""
fallback is counter-productive. It gives the appearance that Netty has been properly shaded when in fact it still collides. As a user, I’d much rather epoll and tcnative obviously fail when improperly shaded. So for me an implicit solution has the benefit of failing when misconfigured. But we can mix-and-match behaviors pretty easily.
Depending on the solution, supporting io.netty.packagePrefix
may not be necessary any more. An explicit configuration by the user (via io.netty.packagePrefix
or similar) may be a necessary supplement to implicit solutions since shading may not use prefixing; io.netty
may have been rewritten as a.b
or com.example.shadednetty
.
I’d be willing to submit a PR for necessary changes, although I’d hope we could agree on an approach first.
Issue Analytics
- State:
- Created 6 years ago
- Comments:8 (8 by maintainers)
Top GitHub Comments
I’ll send out a PR then using the “Semi-readable implicit” approach then. Truth be told, @normanmaurer, you didn’t slow down the PR at all 😄.
Unless someone says otherwise, I’ll keep
io.netty.packagePrefix
for the moment to 1) give time for users to try the implicit method and find issues and 2) ease migration from the system property. If things work out and it is redundant then it is easy to remove it in the future.@johnou, not really, since there isn’t an explicit API.