- Krakatau (Python)
- GNU make (C)
- git (C)
- javac, jar (ELF binaries that invoke Java)
- javap (alternative to Krakatau's disassemble.py; another ELF binary that invokes Java)
After repeating this workflow by hand for numerous JAR files, I figured it was worth automating.
Arguably the "disassemble" step could have been integrated a little better using e.g. jython or "import Krakatau", but I didn't feel that it was worth the trouble. Also, structuring it this way makes it easy to substitute jasper/jasmin or another bytecode (dis)assembler if desired.
The "reassemble" (make) step would have to be completely redesigned to use pure Java tools. Changing to Ant/Maven/Gradle/... might be helpful if the instrumentation has more complicated dependencies. For my purposes, GNU make was the most expedient solution.
Shelling out to run the binaries has the added advantage of making it easy to switch between different JDK versions.