
If you are a Liferay portal developer, then you already know that OSGi is the core technology behind Liferay Portal. Most of our day-to-day work involves creating custom OSGi modules to meet project requirements. Yet, even though we work with OSGi all the time, many of us are still unaware of its true power.
One of the biggest and most underrated problems OSGi solves is something called JAR Hell.
In this post, we’ll understand what JAR Hell really means and how OSGi elegantly solves it in the context of Liferay Portal—without going too deep or theoretical.
What is JAR Hell?
In simple terms, JAR Hell happens when multiple versions of the same library exist in an application, and the JVM gets confused about which one to use.
This usually leads to errors like:
ClassNotFoundExceptionNoSuchMethodErrorNoClassDefFoundError- Unexpected runtime behavior
A real-world example
Imagine your Liferay project uses:
- Library A → depends on
commons-lang:2.6 - Library B → depends on
commons-lang:3.12
Both JARs are present in the classpath.
Now the JVM loads only one version, and if the wrong one gets loaded first, your application breaks at runtime. This is classic JAR Hell.
In traditional Java applications (WAR/EAR), this problem is very common and very painful to debug.
Why JAR Hell is a Big Problem in Liferay
Liferay is:
- Huge
- Modular
- Extensible
- Built on top of many third-party libraries
Without a proper module system, managing dependencies at this scale would be nearly impossible.
That’s exactly where OSGi becomes a game changer.
How OSGi Solves JAR Hell
OSGi does not use a flat classpath like traditional Java applications.
Instead, it introduces strong modularity.
Let’s break it down simply.
1. Each OSGi Module Has Its Own Classloader
In Liferay, every OSGi module (bundle) has its own classloader.
This means:
- Module A can use
commons-lang:2.6 - Module B can use
commons-lang:3.12 - Both can run side by side without conflict
No more global classpath pollution.
2. Explicit Dependency Declaration
In OSGi, you don’t accidentally access classes.
You must explicitly say:
- What packages you export
- What packages you import
- Which versions you accept
Example (conceptually):
Import-Package: org.apache.commons.lang3;version="[3.12,4)"
This makes dependencies:
- Clear
- Predictable
- Version-safe
3. Versioned Packages, Not Just JARs
Traditional Java thinks in terms of JAR files.
OSGi thinks in terms of packages with versions.
So instead of:
“Which JAR is loaded?”
OSGi asks:
“Which package and which version does this module need?”
This fine-grained control is one of the strongest weapons against JAR Hell.
4. True Isolation Between Modules
In Liferay:
- One broken module does not break the entire portal
- You can install, uninstall, or upgrade a module at runtime
- Dependencies are resolved dynamically
This isolation dramatically improves:
- Stability
- Maintainability
- Upgrade safety
JAR Hell Without OSGi vs With OSGi
| Without OSGi | With OSGi (Liferay) |
|---|---|
| Single global classpath | Module-level classloaders |
| Version conflicts common | Multiple versions can coexist |
| Runtime failures | Safe, controlled resolution |
| Hard to debug | Clear dependency visibility |
Why This Matters for Liferay Developers
As a Liferay developer, this means:
- You can safely use different library versions in different modules
- You avoid unexpected runtime crashes
- You get cleaner, more maintainable architecture
- Large enterprise portals remain stable over time
OSGi is not just a framework Liferay uses—it’s the reason Liferay scales so well in complex enterprise environments.
Final Thoughts
Many developers use OSGi in Liferay without fully realizing why it exists.
OSGi’s biggest superpower is not just modularity—it’s ending JAR Hell once and for all.
Once you truly understand this, you’ll stop seeing OSGi as “complex” and start seeing it as a protective layer that saves you from years of dependency pain.
If you’re working on Liferay Portal, mastering this concept will instantly make you a better and more confident developer.

