Often when discussing OSGi at events, over the phone, or online, we hear things like, “Yeah, I like JRebel but now we are using OSGi”, or “Does JRebel support OSGi”, or “Isn’t OSGi the same as JRebel?”. Sometimes it happens that people start comparing OSGi to JRebel, which is kind of like comparing a Skyscraper to a Ferrari; this article is designed to a) explain the differences on a technical level what JRebel and OSGi do, b) outline some ideal use cases for OSGi and JRebel c) clear up any grey areas or misconceptions between the two technologies. So, let’s take a look at JRebel and OSGi.
What is JRebel and what is OSGi?
JRebel is a developer productivity tool. JRebel allow developers to view code changes instantly, it skips the rebuild, restart, redeploy cycle intrinsic in Java development, which enables developers to get more done in the same amount of time and stay in the flow while coding. JRebel supports a majority of real-world enterprise java stacks and is easy to install into existing development environments.
OSGi is a module system and a dynamic runtime where modules (also called bundles) can come and go, but your code has to conform to the requirements of the module system — it is perhaps the only widely used framework for the JVM that enforces real modularity.
In plain speech: OSGi projects are inherently more modular than plain Java projects, as long as you follow the rules — for example, to use classes from another module, that module needs to declare that it exports the packages containing those classes.
Bottom line: JRebel is a productivity enhancer for anything Java that works with your normal tech stack, while OSGi is at its core a rather strict module system that forces you to conform it.
If JRebel and OSGi are so different, why do people compare them?
Probably because both JRebel and OSGi are capable of fast or instant class reloading during development. However, with JRebel this is the pure goal, whereas with OSGi this is more of a side-effect. In the end, using OSGi means switching to a brand new framework and container, while JRebel quickly plugs into your existing stack.
JRebel instantly reloads changes you make to class structures (e.g. adding/changing/removing methods, constructors, fields, classes, annotations, static field values, interfaces, etc.) so that you see immediately what your code changes look like, regardless of IDE, application server, or frameworks.
In OSGi, modules can, in certain cases, be stopped, reloaded and started again with hardly any noticeable downtime. But if that module has dependent modules, this will cause a cascade effect of reloads. (JRebel monitors all of the code in your workspace and automatically reloads changes to it in less than 1 second). OSGi’s reloading is better suited for not taking down production systems to upgrade bundles, but in development still takes you out of the flow.
What should I know about OSGi?
OSGi is a well-known system for enforcing modularity on the JVM — tools like PDE and BndTools will validate the module boundaries and their dependencies as you edit, and your code will not run under an OSGi runtime if it tries to ignore the boundaries.
The OSGi Alliance claims that the framework and the enforced modularity will yield benefits such as ease of component reuse, reduced complexity (if your system already has complex dependencies), ease of deployment, dynamic updates, resilience to change, proper versioning, escape from JAR hell, simplicity etc.
Some of these claims are facts, but may or may not apply to your specific case. Others can be debated, and people have. There are both success stories and not-so-awesome stories about implementing OSGi.
OSGi increases modularity and dynamism
OSGi can benefit your project under the following circumstances:
- You want more modularity because you have:
- a complex set of dependencies
- lots of reusable pieces
- customizations of your software in different contexts
- a chaotic mess of a system that needs some order introduced into it
- You want more dynamism because:
- you want to be able to install and uninstall services or plug-ins into a running system
Not every system meets the description, and if you don’t feel the need for any of it, it’s unclear whether OSGi will help you or actually introduce more complexity than it removes. Of course, each individual case is different.
OSGi can dynamically reload changes
Because the OSGi runtime is dynamic, where bundles can be installed, started, stopped and uninstalled, it is possible in some cases to simply stop a module, reload it, and start it again. Of course, if other modules depend on the reloaded module, they will have to be stopped and rewired to the new version as well.
It’s worth considering that if bundles have internal state that is not restored at startup, reloading them will lose that state. This means that when you’ve filled a form, navigated to a new page and then reload a bundle, you need to take these steps again…and your program state gets nuked during the reload.
OSGi recreates classloaders
OSGi’s runtime is very much based on classloaders – each bundle gets it’s own classloader, with references to classloaders of other bundles – the module’s dependencies. OSGi handles reloading by dropping the entire module classloader and creating a new one – it does not reload single classes or try to preserve their state.
JRebel has a lot to do with classloaders as well – it hooks into existing classloaders to make the classes loaded through them instantly reloadable (while maintaining state), and this works with or without OSGi.
So can I use JRebel and OSGi together?
OSGi and JRebel are not directly comparable nor competing with each other. As far as JRebel is concerned, OSGi is just another runtime. There is a small overlap as both allow some form of reloading code in a running application, but for most uses of OSGi that is a side effect more than a goal, and isn’t guaranteed to ever work properly. For JRebel, it’s the main feature.
JRebel supports reloading code in OSGi applications, so there is a way to use both together. Ideally, you could let JRebel reload most changes to code in a bundle, and let OSGi reload the entire bundle if changes become larger e.g. if a dependency was added, or the bundle’s activation sequence was modified.
We’ve already seen that OSGi is concerned with your application’s architecture as well as design, and requires both effort on your part and a whole ecosystem around it – you can’t use third-party libraries unless they have been “osgi-ified” either by the original library developers, someone else, or you.
JRebel doesn’t concern itself with modules, and is meant to be transparent. It is a single JVM plugin that tries to stay out of your way and make Java development as seamless as with scripting languages. JRebel is only concerned with reloading your code and static resources, whatever existing Java technologies you are using — you don’t need to change anything about the way you and your team is developing.
With JRebel, you only need to spend a few seconds providing a mapping from your running application to resources in your workspace, where the changes are made during development. And even this mapping can be generated by Maven, Gradle, or IDE plug-ins in most cases.
What should I take away from this?
To put it bluntly, implementing OSGi should be done when the end goal is to achieve modularity and dynamism, but this requires continuous effort on your part; using JRebel is about increasing productivity by making Java as fast and iterative as Python, PHP or Ruby. It just requires a download and pressing a couple of buttons in your IDE. The two aren’t mutually exclusive and serve very different purposes.
Perhaps you shouldn’t go for OSGi in a new project if all you expect to gain is increased productivity through quick code reloads. OSGi is made for projects that require a highly modular architecture. Regardless of your needs, JRebel can help you in either case.
If you have any questions you can find me on twitter at @akoblentz or leave a comment below!