This article is from my translation of the Infoq Chinese station, the original address is: Http://www.infoq.com/cn/news/2015/12/jigsaw-jar-hell
Nicolai Parlog is a passionate software engineer, a fanatical supporter of digital copyright and open source software, and has made important contributions to Assertj, Controlsfx, FindBugs and Property alliance projects. Recently, Parlog on the Jigsaw Project wrote an article about the jigsaw project some shortcomings and improvements. One of the goals of the Jigsaw project, which is ambitious, is to get rid of the jar hell problem in the most error-prone and problematic classpath mechanisms. However, while other goals of the project will be achieved in the near future, the goal of solving the jar hell problem does not seem to be easy.
To get a better understanding of what we're going to discuss next, take a look at the jar hell problem, and then explain what the jigsaw project will do to solve the problem, and why Jigsaw's attempt to solve the problem does not have an intrinsic impact on the entire problem domain. Finally, let's take a look at the official stance on this topic and give a proposal on how to prevent the advent of module hell.
Jar Hell problem
Jar Hell has the following cyclic problems:
- Ambiguous expression and transitive dependence
- Covered
- Version conflict
- Complex class loading
Depending on the capabilities and features of the build tool and component system (which the JDK developer calls the container), we can see that the ambiguity and the transitive dependency problem have been solved to a great extent, the masking problem has at least been mitigated, and the complex class loading is no longer a commonplace problem. In this way, version conflicts become one of the most serious problems in Jar hell, and it affects many of the daily update decisions of many projects.
What changes will the jigsaw bring?
I've previously introduced the new features that Jigsaw project will bring to Java 9, but this will be explained from a different perspective. First, it will be affected by the current version of the previous access build, and secondly, we'll only introduce it from the perspective related to the jar/module hell.
The core concept that Jigsaw brings to Java is modularity. In short, a module is like a jar with some additional information and features. This information contains the name of the module and the names of the other modules that the module depends on.
Depend on
When the compiler and the JVM are processing the module, they parse the information. When compiled or started, they parse all dependencies through the module path transitivity. In general, this is similar to classpath scanning, but it is now looking for the entire module rather than a single class, and for the JVM, this is the start-up period, not the run-time. If all dependencies cannot be found on the module path, then the transitive dependency of the parsing module fails. This clearly solves the problem of unclear expression and endless transitive dependency. I think it's a great idea that the Java language now officially knows about dependencies, and all the tools (compilers and JVMS, etc.) can understand this and use it properly! However, I don't think this will have any positive impact on the developer's daily work, as many existing infrastructures have already solved the problem, such as building tools.
Covered
Jigsaw eliminates the problem of shadowing. The module system ensures that each dependency is implemented by another module, and each module reads up to one module, and the modules that define the same-name package do not interfere with each other. To be more precise, the module system terminates and errors when it encounters ambiguity, such as two modules exporting the same package to the same module.
Version conflict
We believe that the version conflict of third-party libraries is the most difficult problem for jar hell to solve. The most straightforward solution is that a modular system can load different versions of the same module. This requires ensuring that there is no interaction between these versions. The problem: In a single configuration, it is not necessary to support multiple versions of a module. In fact, the current build will neither create nor understand the module version information. Some workarounds have been used in some ways. The ugliest, and most feasible, way is to rename conflicting artifacts so they are no longer two different versions of the same module, but two completely different modules. This, however, proved unworkable at last. Obviously, make sure that "the module that defines the package with the same name does not interfere with each other" is implemented by rejecting any boot configuration when two modules export the same package. Even if no module reads them!
Complex class loading
How the module interacts with the ClassLoader and how to change the complexity of class loading is a tricky issue. In fact, the module system does not have much restriction on the relationship between the module and the ClassLoader. The ClassLoader can load types from one module or multiple modules, as long as there is no mutual interference between the modules, and the type in each module is loaded by only one loader. Therefore, the class loader is a one-to-many relationship with the module.
Module Hell?
Since the dependency and masking issues have been resolved and the class loading problem has been improved, why should I discuss the module hell? Is it because of the version conflict? That's right! If Jigsaw wants to solve the jar hell problem, it needs to pay particular attention to version conflict issues. Otherwise, many projects will not show any improvement. They still face version conflicts and fall into the nightmare of customizing the ClassLoader.
Proposal
My proposal is to give developers and build tools the ability to pass on some extra information that can solve some ambiguous problems. The two common ways to pass this information are the command line and the configuration file. If you use command-line arguments, you need to enter each time you start. Depending on the amount of information and the size of the project, this approach can become tedious. You can create a configuration file from the build tool and then specify the configuration file from the command line. This seems like a good solution. At present, the initial module and all transitive dependencies are resolved by a single configuration, which forms a single level. However, we can load multiple versions of the same module into different tiers at run time, which is what the component system does. In general, my advice is to explicitly specify configurations through multiple hierarchies.
Will the jigsaw project solve the Java jar hell problem?