Hacker News new | ask | show | jobs
by shawnz 2233 days ago
The JVM supports hot code loading, although this article seems to imply only BEAM supports it.
2 comments

The article mentions "The JVM allows you to change the code while the program is running."

However, that's not quite the same thing. The JVM allows you to change instructions, but not -data-. That is, in between versions you change what data a class contains, there is no way to change it out from the running instance. The JVM either has one version of the bytecode loaded, or the other; it has no concept of transitioning between them.

The BEAM has a mechanism to do that. It can have both loaded. And you can write transformation functions to allow the internal process state to transform from one to the other.

Per the article, "Hot code loading means that the application logic can be updated by changing the runnable code in the system whilst retaining the internal process state" - emphasis added. That's the key bit for maintaining uptime during an upgrade. Honestly, I don't think it's used that often, but it's there.

You can do that on the JVM too, just use separate classloaders and let the new objects reflect over the old to transition data across. It's not widely done though, for sure.
How do you move data? That Foo object that previously referenced both a Bar and a Baz, but you refactored it so now the Bar, not the Foo, has the reference to the Baz? Or where you changed the type of Baz from Gleep to Glorp?

Erlang, due to how actors encapsulate state, and dynamic typing, allows you to do those things pretty trivially.

There are frameworks that support this kind of evolution, e.g. Kryo can do graph->graph transformations without intermediate serialisation I believe. Or you could write it by hand. If the static typing gets in the way you can always just use a scripting language to do it, many run on the JVM.
Do you have a reference on that?

I want to make sure you're talking about the same thing.

Clojure does hot code reloading as a built in. You essentially send code to a running system and you change it. It’s enabled by a dynamic class loader. I wouldn’t say it’s common outside of Clojure though, the whole language and ecosystem is built around this concept.

To be clear: JVM enables the feature, so “technically” JVM allows hot code reload. Not sure how useful this is in practice for non-Clojure JVM users.

Runtime code generation is a common optimization in java frameworks. End-users may never see it but the majority of popular frameworks use it under the covers.

Debuggers also use the functionality to allow live code editing and expression evaluation when paused on a breakpoint

Eclipse, IntelliJ and Netbeans all support it out of the box for Java code.
ClassLoader [1] in the small, and OSGi [2] in the large, are good starting points for comparison.

[1] https://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoa...

[2] https://en.wikipedia.org/wiki/OSGi

generating code during runtime is rather common in Java frameworks. Most really popular frameworks use it. Spring for AOP and Hibernate for "bytecode enhancement". There's a number of libraries, like CGLIB and ByteBuddy designed explicitly to make this easy.

There are limits to how much you can change in existing loaded class code, but if you are just loading up new dynamically generated code you can do pretty much anything.

Its a big reason why some of these Java frameworks are so fast. They can generate highly optimized code on the fly, load it, and have it running alongside the existing app code within a few hundred milliseconds. And the Java JIT will optimize it as if the code was there the whole time.

This makes performance optimizations easy that would be impossible in AOT languages like Go, C, C++, Rust, etc

java.lang.invoke.MutableCallSite supports linking one particular MethodHandle at a time which the VM will optimize for. Then you can use MutableCallSite::setTarget with another MethodHandle which will cause recompilation of affected paths.