Skip to content

Latest commit

 

History

History
59 lines (53 loc) · 2.99 KB

File metadata and controls

59 lines (53 loc) · 2.99 KB
jlbp
id
JLBP-18
permalink /JLBP-18

Only shade dependencies as a last resort

Shading is a process where a dependency is relocated to a different Java package and copied into the same JAR file as the code that relies on that dependency. The main purpose of shading is to avoid conflicts between the versions of dependencies used by a library and the versions used by the consumers of that library. Most implementations of shading do a simple search and replace of Java package strings in the byte code of the dependency classes and the code using the dependency classes.

There are a number of problems with shading:

  • It can cause considerable size bloat. If it is applied at multiple layers, it can have a massive accumulating effect.
  • Users cannot upgrade dependencies shaded by other libraries (which means security fixes to a transitive dependency need to wait for the shading library to also roll in the security fix).
  • Shading cannot be performed on types used in a library's own public API as return types or method arguments.
  • Shading often corrupts non-code metadata in META-INF/MANIFEST.mf and other locations. For instance, service entries under META-INF/services are hard to merge because the entries are located in the same place for every JAR file.
  • Shading doesn't relocate JNI code.
  • Shaders either don't support classes loaded by reflection or they replace all strings matching selected packages in the bytecode, leading to the corruption of some constants.
  • It is easy to accidentally fail to relocate classes or other files, resulting in an artifact that overlaps classes and files with the original dependency (creating the situation described in JLBP-5).
  • Shading violates many closed source licenses. If the license contains language such as "You must not reverse engineer, decompile, disassemble, modify, or translate the Software", you should consult an attorney before shading. Shading is compatible with open source licenses.
  • Shading breaks code browsing and debugging in many IDEs. Eclipse, for example, cannot locate the original source code for a shaded class.

For these reasons, shading should be used sparingly, especially for libraries consumed by other libraries (because of the snowball effect).

If you shade, you need intimate knowledge of how your dependencies work, and you need to read the source code. Make sure you do all of the following:

  • Add a test to make sure that all classes and other files copied into your JAR file from your dependencies are relocated.
    • Other files include configuration files (for example log4j.properties).
  • Promote transitive dependencies that are not relocated to direct dependencies.
  • Make sure no dependencies that appear on your own library surface are relocated.
  • Make sure that all service files are merged correctly.
  • Make sure to relocate JNI library names.
  • Confirm that the licenses of the dependencies that you are shading are compatible with being re-released within your artifact.