Jar package conflicts are often encountered in work, especially middleware landing. This article will analyze current jar package isolation solutions in the industry.

The nature of JAR package conflicts

Java applications do not load the right classes for some reason, causing them to behave differently than expected.

Two. Jar package conflict two cases

Class 1 JAR package conflicts (different versions of the same JAR package)

  1. There are multiple versions of the same Jar that the application depends on, and the wrong version is chosen so that the JVM does not load the required classes or loads the wrong version of the classes.
  2. There are three necessary conditions for this problem to occur:
  • Multiple versions of the same JAR package appear in the dependency tree.
  • Interface changes (class name, method signature changes, method behavior changes) between versions of the JAR package
  • Maven’s arbitration mechanism chose the wrong version

The second type of JAR package conflict problem (different jar packages have different versions of the same class)

  1. The same class (with exactly the same fully qualified name) appears in multiple dependent JARS, that is, there are multiple versions of the class, and the JVM loads the wrong version of the class due to the order in which the JARS are loaded (Maven’s shortest path and overwrite first). For example, if there are three JAR packages A, B, and C, the class loader will not load the class in the other JAR packages after it first loads the class from JAR package A because of the dependent path length, declaration sequence, or file loading sequence of the file system.
  2. There are three necessary conditions for this problem to occur:
  • The same class M appears in two (or more) different JAR packages A and B.
  • Class M has different behaviors in A and B.
  • The loaded class M is not what we want.

Solution

Method 1: Manually rectify the fault

  1. Determine the name of the class causing the conflict based on the exception stack information.
  2. MVN Dependency: tree-dverbose -Dincludes=

    :

    to see where the version of the JAR package was introduced.

  3. If category 1 Jar excludes, use < Excludes > to exclude the unnecessary Jar version or declare the version in dependencyManagement.
  4. If it is a Class 2 Jar conflict, if you can exclude it, use

    to exclude the unwanted Jar, or consider upgrading the Jar or changing it to another Jar.

The implementation of isolating containers in Blog Java talks about treating each JAR package as multiple bundles, running in isolation through a custom ClassLoader, and realizing that multiple Jars share a class. The Demo runs by starting a KContainer class that contains a BundleList and a SharedClassList. Each Bundle represents a jar package or class path. The Bundle class contains a custom BundleClassLoader class (inherited from UrlClassLoader). The BundleClassLoader needs to pass in a SharedClassList. If the classloader does not load a class, it can load it from the SharedClassList. In this way, multiple JAR packages share a class.

protected Class<? > findClass(String name) throws ClassNotFoundException {logger.debug(" try find class {} ", name); Class<? > claz = null; try { claz = super.findClass(name); } catch (ClassNotFoundException e) { claz = null; }if(claz ! Logger. debug(" Load from class pathfor{} ", name);returnclaz; } // If not, load from the shared class claz = sharedclasses.get (name);if(claz ! = null) {logger.debug(" Load from shared classfor{} ", name);returnclaz; } logger.warn(" not found class {} ", name); throw new ClassNotFoundException(name); }Copy the code

Classes that need to be shared to others can be specified in the classpath through a properties file that is loaded into SharedClassList at loadBundle time.

SOFAArk also uses different class loaders to load conflicting three-party dependencies, so that they can coexist in the same application runtime. SOFAArk uses the Ark Plugin to distinguish which dependencies in an application need to be loaded by a separate classloader. With SOFABoot’s Maven package Plugin, developers can package several ordinary JAR packages into Ark Plugin provisioning dependencies or transform ordinary Java modules into Ark Plugins. The Ark Plugin is introduced by adding Maven dependencies to the application. At runtime, the SOFAArk framework will automatically identify whether the Ark Plugin is contained in the application’s tripartite dependency package and load it using a separate class loader. The runtime logic diagram is as follows:

  1. The SOFAArk container is the lowest level and is responsible for starting the application.
  2. Each Ark Plugin is loaded by the SOFAArk container using a separate classloader, isolated from each other.
  3. Application business code and other common third-party dependencies that are not Ark Plugins are collectively referred to as Ark Biz. Need to rely on the underlying Ark Plugin.

In the POM file of the Ark Plugin, the exported class and the imported class are configured. Exporting classes means exporting the classes in the Ark Plugin to Ark Biz and other Ark Plugins for visibility. For the Ark Plugin, if an exported class of another Ark Plugin needs to be used, it must be declared as its own imported class.

Method 4: Alibaba’s Pandora isolation container Ali’s Pandora is a closed source, with less online information. As can be seen from a PPT of Ali’s speech, Pandora is still based on ClassLoader implementation and such isolation container disadvantages of Pandora:

  1. The usage is complicated and difficult to understand.
  2. The startup is slow, and users cannot select as required
  3. Debugging difficulty
  4. Deployment, operation and maintenance are difficult

The next article will focus on the use and source code analysis of ANT Financial SOFA-ARK container