Using DCEVM / Hotswap Agent in Java development

Using DCEVM / Hotswap Agent in Java development

Hotswapping Java code is a technique that can save a lot of programmer down time when you’re working with humongous web applications that take forever to start up. It allows you to see the effect of code changes while the application remains up and running. It works by recompiling and reloading the changed classes.

The Java JVM supports hotswapping out of the box but in a very modest way. The capabilities of your standard vanilla JVM are limited to being able to hotswap the code for a method body and not much else. If you add, remove or rename methods, change their arguments, or make other changes to your code the JVM has no way of reflecting those changes in the loaded classes of the running process.

There are some third party tools available that can interfere with the inner workings of the JVM and make it possible to reload classes with a much broader range of changes. The best known of these is JRebel. It works great, and there is no doubt that this is a very useful weapon in the Java developers arsenal. But it is not free.

In this article I will introduce DCEVM / Hotswap Agent and explain how to use this toolset. It can do most of the things JRebel does, is open source and free as in free beer. Here is a quick comparison based on my own research:

Change JRebel DCEVM / Hotswap Agent Vanilla JVM
Modify method body Y Y Y
Add and remove method Y Y N
Modify method definition Y Y N
Add and remove field Y Y N
Add and remove class Y Y N
Add and remove inner class Y Y N
Add, remove and modify static field value Y Y N
Add and remove enum value Y Y N
Add and remove annotation Y N N
Add and remove implemented interface Y N N
Replace superclass Y N N

How it works (more or less)

The tool monitors your classpath looking for changes in classfiles. When you edit your Java code and let your IDE recompile the affected sources the changes are picked up and the changed classes are reloaded into the JVM, while the process using those classes remains running. In order to make the reloaded class totally replace the originally loaded class in the JVM, all kinds of updates must be made to the metadata that your JVM keeps track of for loaded classes. What goes on exactly with lists, tables and references in the inner workings of the JVM is highly technical stuff and to be honest, I haven’t really looked into it.

Suffice to say that it takes a special version of the JVM to be able to do this. In the case of DCEVM / Hotswap Agent, this is the DCEVM part. The name stands for Dynamic Code Evolution Virtual Machine. It is implemented as an alternative version of one of the dynamic link libraries used by the JVM, jvm.dll for Windows and libjvm.so for linux.

Then there is a separate Java Agent, called Hotswap Agent. A Java Agent is a component that provides instrumentation capabilities to an application. In the case of Hotswap Agent, the capabilites involve dealing with all kinds of frameworks that have their own system of classloaders such as Spring, Tomcat etc. Hotswap Agent ensures that such frameworks respond correctly to the reloading of classes.

To sum it up, in order to do hotswapping you will need to

  • install DCEVM
  • download the Hotswap Agent jar file
  • add VM arguments to your launcher to activate both DCEVM and Hotswap Agent
  • optionally create configuration

Install DCEVM in Java 8

You can turn an existing installation of the JVM into a DCEVM version by patching it. Download the patcher program, start it and then select the directory where your JDK lives in order to patch it. The patcher program itself is a Java jar called DCVM-8u181-installer-build2.jar which you can download from here.

The patcher program offers you a choice to either replace the standard JVM with DCEVM or install DCEVM alongside as altjvm. If you select the replace option, you won’t need the -XXaltjvm argument in your program launch VM arguments but you also won’t be able to switch hotswapping off. Therefore I recommend the other choice in the patcher program, Install DCEVM as altjvm.

Patching the JDK in this way does not alter the Java VM itself. A special version of the main jvm library is installed (in jre/lib/dcevm/) which is used instead of the vanilla library when starting the JVM with this command line argument:

    java -XXaltjvm=dcevm -version
      openjdk version "1.8.0_252"
      OpenJDK Runtime Environment (build 1.8.0_252-8u252-b09-1~18.04-b09)
      Dynamic Code Evolution 64-Bit Server VM (build 25.71-b01-dcevm-light, mixed mode)

Important note for Windows: the latest supported version of Java 8 is 1.8.0_u181 . The DCEVM provided on Github will simply not work with later versions. You can find archived versions of the JDK here. Of course, using an ancient version of the JDK introduces a certain security risk. In general this should not be a big problem if you run it only on a development machine which usually sits protected behind a corporate firewall.

Install DCEVM in Java 11

For Java 11, there is no patch program. Instead, you need to install a special version of the JDK that you can download from here.

My advice would be to install it separately from your regular version of JDK 11 and then choose which one to use in your debug session via configuration options in your IDE.

Download the Hotswap Agent jar file

You can download it from here. The same jar is used for both Java 8 and Java 11. After downloading, you must keep track of where you left it as you will need to supply the full pathname as one of the VM arguments for your program.

Arguments for the VM

After installing the DCEVM and downloading the Hotswap Agent jar file, you can start using them in your IDE by adding these arguments for the JVM that you use for running and debugging your application (note: these are arguments for the VM, not regular program arguments):

     -XXaltjvm=dcevm -javaagent=<full path to Hotswap Agent jar file>

When you then run your application in debug mode, you can see various log messages indicating that hotswapping with Hotswap Agent and DCEVM is active:

HOTSWAP AGENT: 17:06:31.669 INFO (org.hotswap.agent.HotswapAgent) - Loading Hotswap agent {1.3.0} - unlimited runtime class redefinition.
HOTSWAP AGENT: 17:06:32.099 INFO (org.hotswap.agent.config.PluginRegistry) - Discovered plugins: [Hotswapper, JdkPlugin, AnonymousClassPatch, ClassInitPlugin, WatchResources, Hibernate, Hibernate3JPA, Hibernate3, Spring, Jersey1, Jersey2, Jetty, Tomcat, ZK, Logback, Log4j2, MyFaces, Mojarra, Omnifaces, Seam, ELResolver, WildFlyELResolver, OsgiEquinox, Owb, Proxy, WebObjects, Weld, JBossModules, ResteasyRegistry, Deltaspike, GlassFish, Vaadin]
...
INFO: Starting Servlet engine: [Apache Tomcat/9.0.35]
HOTSWAP AGENT: 17:06:33.082 INFO (org.hotswap.agent.config.PluginRegistry) - Plugin 'org.hotswap.agent.plugin.tomcat.TomcatPlugin' initialized in ClassLoader 'ParallelWebappClassLoader
  context: testsite
  delegate: false
----------> Parent Classloader:
[email protected]
'.
HOTSWAP AGENT: 17:06:33.082 INFO (org.hotswap.agent.plugin.tomcat.TomcatPlugin) - Tomcat plugin initialized - Tomcat version '9.0.35.0'

You can now change some code in your IDE, hit <Ctrl><F9> or whatever to rebuild your project and view the log messages reporting the successful reloading of your changed classes.

Configuration

In most cases, Hotswap Agent needs no additional configuration. It uses the classpath to determine which class files to monitor for changes. You can add a configuration file src/main/resources/hotswap-agent.properties in which you can add extra classpath information for when your project has dependencies on a jar file that may also change during the course of a debug session. You can also add extra directory information for other resources you want Hotswap Agent to monitor.

Additional notes for IntelliJ

You can install a set of plugins that help in the use of DCEVM / Hotswap Agent. These are the DCEVM Integration plugin and the HotSwapAgent plugin. When you install these you will se an entry named HotSwapAgent in the Tools settings. Here you can configure if and when to use hotswapping and manage some other settings.

Also, after installing the helper plugins IntelliJ will offer to download and install supporting files (notably the DCEVM dynamic load library and the agent jar). I found that this does not always work as expected. You can give it a try by all means but if IntelliJ reports errors you have the description in this article to help you along.

If you manually download the Hotswap Agent, you must set the location in the Tools pane for HotSwapAgent.

When you manage DCEVM and Hotswap Agent activation via the plugins, it will not be necesssary to add the extra VM arguments to your program launchers as this is taken care of by the plugins.

Additional notes for Eclipse

There is no special plugin in Eclipse for managing Hotswap Agent. To use it in Eclipse, make sure that your application is launched with the DCEVM enabled version of the JVM and in the case of Java 8 has extra -XXaltjvm=dcevm -javaagent=/opt/hotswap/hotswap-agent-1.3.0.jar argument for the VM (your version and file location of the agent may be different). When running a servlet container such as Tomcat, you should disable the Auto Reload feature because otherwise both the servlet container and Hotswap Agent will try to do things when classes are recompiled or resources are edited. This page explains it in more detail.

Links

http://hotswapagent.org/index.html

https://github.com/dcevm/dcevm

https://github.com/HotswapProjects/HotswapAgent

http://hotswapagent.org/mydoc_setup_intellij_idea.html

http://hotswapagent.org/mydoc_setup_eclipse.html

https://documentation.bloomreach.com/library/development/develop-with-hotswapagent.html

https://dzone.com/articles/hot-swap-java-bytecode-on-runtime

https://blogs.sap.com/2018/11/01/hotswap-with-hybris-a-free-open-source-alternative-to-jrebel/

Mario Pinkster
Mario Pinkster

Java Developer at Sentia Consultancy