The Java Virtual Machine is ostensibly a bytecode interpreter. The programs are specified in bytecode and the JVM runs them. The interpreter is much slower than running native machine code, which is probably why Java still has a lingering reputation for being slow. However, most JVMs come with a Just-in-Time compiler (JIT). The JIT will compile the JVM bytecode to machine code at runtime. And part of this compilation process is optimization.
These optimizations change the behavior of your code. Calculations are moved around and cached. Methods are inlined. Unnecessary locks are removed. The code becomes smaller and faster. Clojure takes advantage of this JIT, like anything that runs on the JVM.
Today I'd just like to send you some resources to learn more about they JIT. I'm no JIT expert. Those resources will help you better than I can.
Cliff Click is an amazing engineer who built the HotSpot VM at Sun. He knows modern hardware like the back of his hand and I'm always ready to listen to his talks. Here's one he did about all of the work the JVM does, including the JIT.
If you want a thorough overview of how the JIT works, what the different options do, and how to predict what is going on with the JIT, Charles Nutter (JRuby Developer) did a nice presentation all about the JIT.
Oracle has a good illustration of the kinds of optimizations the JIT can do, including a before and after view of a method.
Douglas Hawkins from Azul Systems does a really deep dive of the JIT.
Gil Gene, CTO of Azul Systems, talks about the JIT.
Well, those should keep you busy for a while. The JVM is big and beautiful and complicated. I didn't want that to turn people off from learning Clojure. That's why I created the course JVM Fundamentals for Clojure. Please check it out. It's over 5 hours of video explaining all of the JVM stuff I use as a Clojure programmer.
The JIT is an amazing piece of technology, but it is optimized mostly for sequential execution. People talk about how Clojure is great for parallel execution, mentioning the immutable values and concurrency primitives. But there's unsung heroics going on in Clojure to avoid the heisenbugs you see in Java all the time. That's what we'll talk about next time.