OSGi Community Event 2018 Presentation by BJ Hargrave (IBM)
Abstract: Java 9 introduced the Java Platform Module System (JPMS) as a way to modularize the Java platform and it can be also be used by developers to modularize their own applications, although JPMS lack a number of important features for software running on the Java platform.
As people look to support the latest versions of the Java platform, changes introduced in Java 9 related to JPMS led to the needs for some features in the OSGi Core specification. OSGi framework implementations like Eclipse Equinox and Apache Felix and tools like Bnd were updated to support these new features.
This session will explore the Java 9+ support added to OSGi Core R7 and Bnd and help you learn how to navigate the world of Java 9+ and OSGi.
2. Java 9 introduced the Java Platform Module System (JPMS)
• JPMS was primarily added to Java to enable modularization of the Java
platform
• Internals can be encapsulated to avoid dependencies - sun.misc.Unsafe
• Platform can be safely subset - jlink
• But JPMS can also be used by application code running on the platform
• But migration from plain JAR to module is a huge challenge
• It really depends on the bottom level dependencies going first
3. But JPMS really falls short for general use in applications
• The Java platform is a single code base, so all the modules are built together
and releases together
• Applications are almost never like this, they are composed of many modules
• From many sources including open source projects
• Released individually on their own schedules
• Potential for version conflicts in shared dependencies
4. Main Shortfalls
• Isolation - JPMS uses a single class loader per layer by default. So your non-exported
(private) packages can conflict with someone else’s non-exported (private) packages:
shadowing.
• Identity dependency - Modules depend upon the names of other module not things used
at runtime: classes in packages. So module names are API. As are transitive requirements
• Access restrictions - Reflection is not allowed unless you “open” your module. This is a
challenge for dependency injection and annotation scanning. You often don’t and
shouldn’t know the name of the module which needs to reflect upon you nor should you
put code, which needs reflection, in exported packages.
• Versioning - ??? Someone else’s problem. Like yours!
6. Changes in Core R7 for Java 9+
• Multi-Release JARs (MRJAR)
• Runtime discovery of platform packages
• Bundle can import java.* packages
• Backwards compatible with pre-Java 9 and past releases of OSGi Core
7. Multi-Release JARs (MRJAR)
• A MRJAR file allows for a single JAR to support multiple major versions of the Java platform
• For example, a MRJAR file can depend on both the Java 8 and Java 9 major platform releases,
where some class files depend on APIs from Java 8 and other class file depend on APIs added
in Java 9
• The purpose is to support alternative implementations of select classes to deal with changes in the
visible APIs of the Java platform
• It is not meant as a means to supply new function or new API on different Java platform versions
• Only supported on Java 9 and above
• Multi-Release: true
13. Multi-Release Bundles
• A bundle can be a multi-release bundle when it has Multi-Release: true in its manifest
• When a bundle is multi-release, the framework must look for the presence of a supplemental manifest
in a versioned folder of the bundle
• META-INF/versions/9/OSGI-INF/MANIFEST.MF
• The supplemental manifest, from the highest versioned folder, can contain Import-Package and
Require-Capability headers which replace the headers from the main manifest
• Since the alternate class implementations in the versioned folder can require different dependencies
• As a best practice, a supplemental manifest should not contain additional requirements on
capabilities which are not supplied by the Java platform for the Java version associated with the
supplemental manifest
14. Multi-Release Containers
• In additional to the bundle itself, a bundle’s class path can specify multiple
containers and each container can also be multi-release
• Bundle-ClassPath: ., libs/foo.jar
• A container must have Multi-Release: true in its manifest to be
recognized as a multi-release container
• When a container is a multi-release container, the framework must look in the
versioned folders when attempting to locate a class or resource in the
container
15. Runtime discovery of platform packages
• Now that the Java platform is modularized, the platform can be configured to
load only certain modules
• You can have a smaller, custom runtime that is tailored to the needs of a
specific application => jlink
• So the set of java.* packages provide by the running Java platform is no
longer constant for a specific version of the Java platform!
• So R7 frameworks must ask the platform for the current set of java.*
packages and use that to set the
org.osgi.framework.system.packages property
16. Importing java.* packages
• Bundle have used a requirement on the osgi.ee capability as a proxy for the set of java.*
packages they may require
• Given that the set of available java.* packages can vary, the osgi.ee requirement can
now only be used to express the JVM requirement
• e.g. Java 10 class file support needed
• Bundles are now permitted to list java.* packages in their Import-Package
• This can be used by the framework to resolve the bundle to ensure their java.* package
requirements can be met
• But class loading for java.* packages is still the same: parent delegation
24. Tooling
• Bnd support
• MRJARs
• Import java.* packages when targeting Core R7
• Make jars that are bundles and modules?
• Automatic enrichment of module-info based upon annotations?
• Shading non-exported packages?