Sitemap

Loading Two Versions of the Same Library in One JVM with JPMS

2 min read18 hours ago

--

Press enter or click to view image in full size

Java applications can have dependency conflicts when two components require different versions of the same library. Can we load both versions into one JVM?

Yes. The Java Platform Module System (JPMS) provides the necessary APIs.

What is JPMS?

JPMS was introduced in Java 9 (September 2017) as part of Project Jigsaw (JEP 261).

It addresses several problems in Java:

  • Dependency management: Modules declare their dependencies explicitly. Java checks the module graph during resolution.
  • Encapsulation: Modules control which packages other modules can access.
  • JDK modularity: Developers can create smaller runtime images with jlink.
  • Class isolation: Separate module layers can use separate class loaders.

Before Java 9, applications primarily used the classpath. When two JARs contained the same class, a single class loader typically loaded the first matching definition. This could cause dependency conflicts and runtime errors.

Loading multiple library versions

JPMS provides ModuleLayer, which lets applications create separate module configurations at runtime.

Get Mark Andreev’s stories in your inbox

Join Medium for free to get updates from this writer.

I created a small demonstration using Guava 10.0 and Guava 33.1.0.

Each version runs in a separate module layer with its own class loader:

JVM
|
Application
/ \
ModuleLayer A ModuleLayer B
| |
Guava 10.0 Guava 33.1.0
| |
ClassLoader A ClassLoader B

Both versions contain com.google.common.collect.ImmutableList. The demo confirms that each version has a different class identity and that both can run in one JVM.

The implementation uses ModuleFinder, Configuration.resolve() and ModuleLayer.defineModulesWithOneLoader().

Limitations

The example demonstrates dependency isolation. The two Guava JARs have different JPMS module names.

JPMS does not provide a direct API to unload a module layer. Class unloading depends on garbage collection. Applications must also manage plugin lifecycle and release references when dynamic unloading is required.

For applications that do not need dynamic unloading, this is usually not a problem.

Try it

Source code: github.com/mrk-andreev/demo_jpms-multiversion

Requires JDK 21 or later.

git clone https://github.com/mrk-andreev/demo_jpms-multiversion.git
cd demo_jpms-multiversion
./run.sh

--

--