Developers using dynamic languages, such as Ruby, are used to a quick code-test-debug cycle: making changes to a piece of code and pressing the browser's reload button is often all that's needed to see the latest effects of a code edit. Java developers, by contrast, have to either restart an entire Java VM, or cause an application server to reload a Web application, for code changes to be visible during development.
JavaRebel is a small JVM plug-in. It registers as a Java agent on the JVM. Its purpose is to reload changes to Java classes. It monitors the timestamp on class [files], and as soon as a class is updated, either by the IDE or a compiler, JavaRebel reloads the changes directly into the JVM.
The difference from a regular build cycle is that there is no need to re-deploy your application if you make changes to your classes. For a desktop application, there is no need to restart that application, and for a Web application, you don’t need to restart an app server or re-deploy the application, as you make changes to classes. It’s a huge time-saver. It’s also the model that developers working with dynamic languages, such as Ruby and Ruby on Rails, are used to, and is one reason many developers like those dynamic environments. JavaRebel provides a similar experience for Java applications. For example, in a Web application, you can change your class, recompile it—which is something your IDE will likely do for you—hit reload on the Web browser, and your changes to Java classes will immediately take effect.
JavaRebel is purely a class reloader, and works on any JVM, and with almost any application container. The most popular Web application containers are already supported, and we keep adding support for more.
There are some limitations in terms of the kind of class changes JavaRebel supports: If you replace the superclass, or if you add implemented interfaces to a class, JavaRebel won’t be able to handle that at the moment. All other types of changes, however, including schema changes, such as adding methods, constructors, and fields, as well as changes to method bodies, will be reloaded into the JVM by JavaRebel.
We just released version 1.2, with a focus on correctness as well as framework support. Our overall vision is to let you focus on developing your code without having to restart the JVM for any reason at all, or without having to re-deploy your Web application.
To that effect, we have an SDK, and we extended the API in that SDK to support more flexible extensions to JavaRebel. With this SDK, you can develop plug-ins for JavaRebel. Although JavaRebel is a commercial product, with a license costing around $150, we open-sourced the API for the SDK, including all the work we did on framework integration.
The key reason you’d want to extend JavaRebel is to support more kinds of changes that could be reloaded by the tool. That includes reloading changes in artifacts other than classes. A good example is a framework, such as Spring. Spring support is a key focus for our 1.2 release. In Spring, if you want to add new dependencies to beans on the fly, or add new beans, our latest version can now reload changes you make to Spring dependencies and beans. That way, you can code up those changes, and don’t have to reload your Spring applications for those changes to become visible.
Up to now, we only suggested using JavaRebel as a development tool. A lot of our customers, however, have been requesting similar functionality in production as well, and we want to enable that functionality by the end of this year. In that vein, the second focus for our 1.2 release was around correctness.
Early on in our product, we made some compromises in order to serve the most common cases. However, there are some border cases that you very rarely run into in development, and now we are providing solutions to those border-line cases as well. With these improvements, we are defining very clearly the kinds of changes we’re able to reload. This focus on correctness was necessary to support the use of JavaRebel in production.
Similar to how you can use JavaRebel now in development, using JavaRebel in deployment would update your production classes on the fly. Updating an application in production today can be tedious: If you have a cluster, you have to bring down each node, and you can update only one node at a time. We want to enable a situation where you can update your code [in your cluster] in just seconds. Whatever way you upload your code to a cluster, JavaRebel will attempt to update the classes inside the VMs.
For our upcoming versions, we’ll be focusing on performance. At the moment, we don’t pay much attention to performance, because that is not so important during development. Although performance is adequate for development, we must make sure that JavaRebel’s overhead is something you can live with, including its memory usage. And, of course, performance is very important once you start using JavaRebel in production.
Since dynamic class reloading seems to be such a convenient feature, Artima asked Kabanov if this technology may at some point find itself into the core JVM, perhaps via a JSR proposal:
JVMs since 1.4 have supported HotSwap. HotSwap is limited, because you can only update method bodies, and even that has to be done in a debug session. At the time when that was designed, there was some discussion, and even some design, about the possibility of being able to update class definitions as well. For some reason, that never materialized. I’m not sure why that was not pursued—it may be that the JVM’s design made that very difficult to implement.
Although I can see that such functionality could be a useful part of the JVM, JavaRebel enables this sort of functionality in a different way than HotSwap does. They are completely independent solutions. Even if the JVM will at some point provide class-replacement functionality, that will likely be an extension of HotSwap, and would therefore be done differently from how JavaRebel provides class reloading.
I could, of course, see application servers providing something close to what JavaRebel offers now. I know of one competing technology at the moment, which is part of Oracle’s WebLogic server, and is currently in beta. But that only works on that one application server, whereas JavaRebel can be used in conjunction with many more app servers.
As an engineer, I’d love to explain what our system does, but that’s not something I can talk about much at the moment. A fairly simplistic way of reloading classes would be to wrap a class loader around part of your application, recreate instances of objects, and so on. That would provide a very limited solution that can’t be applied generally. Our solution does not mock around with class loaders: JavaRebel does not create any more class loaders than what is present in your system. It does something different, and it tries to do that very efficiently.