Decompiler
Turn .class / .jar / .war / .zip into readable Java source, with whole-archive output that mirrors the original package layout.
A portable, single-binary Java toolkit extracted and trimmed from
yaklang.
Turn .class / .jar / .war / .zip into readable Java source,
inspect class structure, and convert the Java serialization wire format to and from JSON —
with no JDK, no cgo, and no ANTLR runtime.
One static binary for the CLI, or a single import for the library. No toolchain beyond Go.
Install the javajive command — decompile, inspect, and (de)serialize from your shell.
go install github.com/yaklang/javajive/cmd/javajive@latest
Then try javajive decompile app.jar or javajive classinfo Foo.class.
Add the module and import the unified facade package — one import covers all three capabilities.
go get github.com/yaklang/javajive@latest
See the library quickstart below for usage.
Clone and build the CLI from source.
git clone https://github.com/yaklang/javajive && cd javajive && go build -o javajive ./cmd/javajive
Requires Go 1.22+. The result is a single self-contained binary.
The tables below preserve the results reported on 2026-09-05 for 34 JARs (18,759 flattened units). They are historical measurements, not v0.4.0 acceptance results or proof of behavioral equivalence.
javac errors-Xverify:allThe current audit compares all 38 historical JARs against a fixed baseline and runs isolated semantic round trips. Compilation, JVM verification, method stubs and runtime results are recorded separately. Existing corpus defects remain visible; successful recompilation does not prove equivalent behavior. See the historical JAR audit and semantic audit.
Historical v0.3.0 per-JAR results, as originally reported. See the current audit above for the expanded corpus and remaining defects.
| JAR (classes) | clean / total | clean % | defect classes | syntax err | full round-trip |
|---|---|---|---|---|---|
| commons-codec (106) | 106 / 106 | 100.0% | 0 | 0 | YES |
| gson (183) | 183 / 183 | 100.0% | 0 | 0 | YES |
| commons-lang3 (339) | 339 / 339 | 100.0% | 0 | 0 | YES |
| jsoup (148) | 148 / 148 | 100.0% | 0 | 0 | YES |
| snakeyaml (231) | 231 / 231 | 100.0% | 0 | 0 | YES |
| spring-core (974) | 974 / 974 | 100.0% | 0 | 0 | YES |
| fastjson2 (681) | 681 / 681 | 100.0% | 0 | 0 | YES |
| guava (1,825) | 1,825 / 1,825 | 100.0% | 0 | 0 | YES |
| jackson-databind (773) | 773 / 773 | 100.0% | 0 | 0 | YES |
| okhttp (200) | 200 / 200 | 100.0% | 0 | 0 | YES |
| commons-collections4 (524) | 524 / 524 | 100.0% | 0 | 0 | YES |
| netty-handler (356) | 356 / 356 | 100.0% | 0 | 0 | YES |
| log4j-core (1,184) | 1,184 / 1,184 | 100.0% | 0 | 0 | YES |
| protobuf-java (672) | 672 / 672 | 100.0% | 0 | 0 | YES |
| asm (38) | 38 / 38 | 100.0% | 0 | 0 | YES |
| joda-time (247) | 247 / 247 | 100.0% | 0 | 0 | YES |
| commons-io (346) | 346 / 346 | 100.0% | 0 | 0 | YES |
| commons-compress (566) | 566 / 566 | 100.0% | 0 | 0 | YES |
| httpclient (470) | 470 / 470 | 100.0% | 0 | 0 | YES |
| slf4j-api (54) | 54 / 54 | 100.0% | 0 | 0 | YES |
| logback-core (453) | 453 / 453 | 100.0% | 0 | 0 | YES |
| caffeine (687) | 687 / 687 | 100.0% | 0 | 0 | YES |
| rxjava (1,653) | 1,653 / 1,653 | 100.0% | 0 | 0 | YES |
| javassist (426) | 426 / 426 | 100.0% | 0 | 0 | YES |
| xstream (498) | 498 / 498 | 100.0% | 0 | 0 | YES |
| commons-math3 (1,280) | 1,280 / 1,280 | 100.0% | 0 | 0 | YES |
| HikariCP (75) | 75 / 75 | 100.0% | 0 | 0 | YES |
| jedis (748) | 748 / 748 | 100.0% | 0 | 0 | YES |
| junit (346) | 346 / 346 | 100.0% | 0 | 0 | YES |
| assertj-core (812) | 812 / 812 | 100.0% | 0 | 0 | YES |
| picocli (216) | 216 / 216 | 100.0% | 0 | 0 | YES |
| commons-pool2 (80) | 80 / 80 | 100.0% | 0 | 0 | YES |
| zxing-core (260) | 260 / 260 | 100.0% | 0 | 0 | YES |
| freemarker (1,308) | 1,308 / 1,308 | 100.0% | 0 | 0 | YES |
| total | 18,759 / 18,759 | 100% | 0 | 0 | 34 libs |
Single-thread decompile throughput — end-to-end (unzip + decompile + dump), the production archive path. darwin/arm64, 20 logical cores, Go 1.22.12:
| JAR (classes) | seconds | classes / s |
|---|---|---|
| commons-codec (106) | 0.78 | 136 |
| gson (195) | 0.57 | 339 |
| commons-lang3 (345) | 1.99 | 173 |
| jsoup (238) | 0.88 | 270 |
| snakeyaml (231) | 0.97 | 237 |
| spring-core (978) | 4.00 | 244 |
| fastjson2 (681) | 25.64 | 27 |
| guava (1,892) | 5.66 | 334 |
| total | 40.50 | 115 |
This batch shows JavaJive's own numbers only — all reproducible via
BENCHMARK.md.
We report class-clean rate + full round-trip + a syntax = 0 hard assertion instead of raw error-line counts,
because a single syntax error phase-masks every downstream type error in a whole-jar compile. The single fastjson2
throughput outlier is one oversized method-body tail class; excluding it the other 7 jars average ~268 classes/s.
The head-to-head comparison against CFR 0.152 and Vineflower 1.10.1 is shown below.
Same machine, same 8 JARs, same javac --release 8. The primary metric is defective outer classes / total (lower is better), collapsed to outer classes so it is comparable across tools. JavaJive is syntax-clean so its whole-tree compile is never phase-masked; CFR & Vineflower are compiled per outer class in isolation so their own syntax errors can't mask their defects — a fair, un-masked comparison.
Defective outer classes / total (clean-class rate). Bold = best for that JAR. Lower defect count is better:
| JAR (classes) | JavaJive | CFR 0.152 | Vineflower 1.10.1 |
|---|---|---|---|
| commons-codec (106) | 0/72 (100.0%) | 10/72 (86.1%) | 2/72 (97.2%) |
| gson (195) | 0/73 (100.0%) | 24/73 (67.1%) | 16/74 (78.4%) |
| commons-lang3 (345) | 0/198 (100.0%) | 46/198 (76.8%) | 6/198 (97.0%) |
| jsoup (238) | 0/51 (100.0%) | 5/51 (90.2%) | 2/51 (96.1%) |
| snakeyaml (231) | 0/122 (100.0%) | 10/123 (91.9%) | 2/121 (98.3%) |
| spring-core (978) | 0/649 (100.0%) | 117/649 (82.0%) | 74/649 (88.6%) |
| fastjson2 (681) | 0/529 (100.0%) | 90/530 (83.0%) | 40/529 (92.4%) |
| guava (1,892) | 0/558 (100.0%) | 154/558 (72.4%) | 66/558 (88.2%) |
| total | 0/2,252 (100%) | 456/2,254 (79.8%) | 208/2,252 (90.8%) |
JavaJive beats CFR and Vineflower on every JAR (0 defective outer classes vs 456 / 208). JavaJive numbers re-measured 2026-09-05 (v0.3.0); CFR 0.152 & Vineflower 1.10.1 columns remain the 2026-07-02 same-machine snapshot. Full methodology & reproduction: BENCHMARK.md §7.
Three Java building blocks, one portable module — plus the supporting cast trimmed down to a self-contained core.
Turn .class / .jar / .war / .zip into readable Java source, with whole-archive output that mirrors the original package layout.
Inspect the full structure of a .class file — constant pool, fields, methods, version, and access flags.
Parse and re-marshal the Java ObjectStream wire format with byte fidelity, and convert it losslessly to and from JSON.
No JDK, no cgo, no ANTLR runtime. Cross-compiles to a single static binary for linux / macOS / windows on amd64 and arm64.
decompile, classinfo, and serial subcommands built on the standard library — small, dependency-light, scriptable.
CI compiles real .class / .jar and JDK-serialized blobs with javac/java, then verifies JavaJive against them.
Import the unified javajive package — one import covers decompilation, class parsing and serialization.
import "github.com/yaklang/javajive"
// Decompile a single class, or a whole archive into a directory.
src, err := javajive.Decompile(classBytes)
err = javajive.DecompileArchive("app.jar", "app-src")
// Inspect class structure.
obj, err := javajive.ParseClass(classBytes)
_ = obj.GetClassName()
// Java serialization: binary -> JSON -> binary.
objs, _ := javajive.ParseSerialized(raw) // or ParseSerializedHex(hexStr)
jsonBytes, _ := javajive.SerializedToJSON(objs...)
restored, _ := javajive.SerializedFromJSON(jsonBytes)
out := javajive.MarshalSerialized(restored...)