chapter one

1 First piece of the puzzle

 

This chapter covers:

  • modularity in general and how it shapes a system
  • Java’s inability to enforce modularity (with dire consequences)
  • how the new module system aims to fix these issues

We have all been in situations where the software we’ve deployed refuses to work the way we want it to. There are of course myriad possible reasons but one particular class of problems has been so obnoxious that it got a particularly gracious moniker: JAR hell. Classic aspects of JAR hell are misbehaving dependencies, where some might be missing but, as if to make up for it, others might be present multiple times, likely in different versions. This is a surefire way to crash or, worse, subtly corrupt running applications.

The root problem underpinning JAR hell is that we see JARs as artifacts that have identities and relationships to one another, whereas Java sees JARs as simple class file containers without any meaningful properties. This brings about quite some trouble.

One example is the lack of meaningful encapsulation across JARs: All public types are freely accessible by all code in the same application. This makes it easy to inadvertently depend on types in a library that its maintainers considered implementation details and never polished for public use. They likely hid them in a package called internal or impl but who cares, right?

1.1  What is modularity all about?

1.1.1  Visualizing software as graphs

1.1.2  The impact of design principles

1.1.3  What modularity is all about

1.2  Module erasure before Java 9

1.3  Complications before Java 9

1.3.1  Unexpressed dependencies between JARs

1.3.2  Shadowing of classes with the same name

1.3.3  Conflicts between different versions of the same project

1.3.4  Complex class loading

1.3.5  Weak encapsulation across JARs

1.3.6  Security checks have to be handcrafted

1.4.1  Everything is a module