Decompiling and disassembly made easy#
If you need some piece of Clojure code to execute as fast as possible you will often benefit from examining the code generated by the Clojure compiler from your code. There is a really easy to use tool for that: clj-java-decompiler. You can make the use of this tool super convenient with Calva custom command snippets.
Prerequisites#
Add com.clojure-goes-fast/clj-java-decompiler
as a dependency to the project.
The custom snippets#
You can add some Calva custom commands configuration to be able to decompile or disassemble any Clojure code in your editor with a keyboard shortcut. Here's an example configuration:
"calva.customREPLCommandSnippets": [
{
"name": "Decompile current top level form",
"key": "d",
"snippet": "(require '[clj-java-decompiler.core :refer [decompile]]) (spit \"decompiled-$top-level-defined-symbol.java\" (with-out-str (decompile $top-level-form)))"
},
{
"name": "Decompile current form",
"snippet": "(require '[clj-java-decompiler.core :refer [decompile]]) (spit \"decompiled.java\" (with-out-str (decompile $current-form)))"
},
{
"name": "Disassemble current top level form",
"key": "b",
"snippet": "(require '[clj-java-decompiler.core :refer [disassemble]]) (spit \"bytecode-$top-level-defined-symbol.class\" (with-out-str (disassemble $top-level-form)))"
},
{
"name": "Disassemble current current form",
"snippet": "(require '[clj-java-decompiler.core :refer [disassemble]]) (spit \"bytecode.class\" (with-out-str (disassemble $current-form)))"
}
],
Now, with the cursor anywhere in a top level defined function, you can spit out a file with the Java code generated for that function by pressing ctrl+alt+space d
. For the byte code, press ctrl+alt+space b
. The files will be generated in the same folder as the Clojure file and be named decompiled-<function name>.java
and bytecode-<function name>.class
, respectively.
To decompile or disassemble the current form (or selection) press ctrl+alt+space space
and pick the desired command from the quick pick menu that pops up. You can add key
to these too if you want even quicker access, of course. The filenames for the results will here be named without any function name suffix, because there is often no function name that can be used.
See this video for a demo.