pure Go no cgo no JDK MIT licensed

Java tooling, in pure Go. Decompile, parse, (de)serialize.

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.

cross-tested against a real JDK CI on linux / macOS / windows

Install

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.

Historical benchmarks · v0.3.0

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.

100%
class-clean rate — 18,759 / 18,759 flattened units recompile with zero javac errors
0
syntax errors across all 34 JARs — a CI-enforced hard assertion, so the numbers can't be phase-masked
14 / 14
self-hosted algorithms — MD5 · SHA-256 · CRC32 · quicksort · Base64 + control-flow seeds — round-trip byte-for-byte
34
libraries with full round-trip: recompile → repackage → JVM -Xverify:all
115 / s
classes per second, single-thread end-to-end decompile (per-class concurrency scales near-linearly)
100%
JVM opcode parse coverage

Current validation · v0.4.0

The 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 / 106100.0%00YES
gson (183)183 / 183100.0%00YES
commons-lang3 (339)339 / 339100.0%00YES
jsoup (148)148 / 148100.0%00YES
snakeyaml (231)231 / 231100.0%00YES
spring-core (974)974 / 974100.0%00YES
fastjson2 (681)681 / 681100.0%00YES
guava (1,825)1,825 / 1,825100.0%00YES
jackson-databind (773)773 / 773100.0%00YES
okhttp (200)200 / 200100.0%00YES
commons-collections4 (524)524 / 524100.0%00YES
netty-handler (356)356 / 356100.0%00YES
log4j-core (1,184)1,184 / 1,184100.0%00YES
protobuf-java (672)672 / 672100.0%00YES
asm (38)38 / 38100.0%00YES
joda-time (247)247 / 247100.0%00YES
commons-io (346)346 / 346100.0%00YES
commons-compress (566)566 / 566100.0%00YES
httpclient (470)470 / 470100.0%00YES
slf4j-api (54)54 / 54100.0%00YES
logback-core (453)453 / 453100.0%00YES
caffeine (687)687 / 687100.0%00YES
rxjava (1,653)1,653 / 1,653100.0%00YES
javassist (426)426 / 426100.0%00YES
xstream (498)498 / 498100.0%00YES
commons-math3 (1,280)1,280 / 1,280100.0%00YES
HikariCP (75)75 / 75100.0%00YES
jedis (748)748 / 748100.0%00YES
junit (346)346 / 346100.0%00YES
assertj-core (812)812 / 812100.0%00YES
picocli (216)216 / 216100.0%00YES
commons-pool2 (80)80 / 80100.0%00YES
zxing-core (260)260 / 260100.0%00YES
freemarker (1,308)1,308 / 1,308100.0%00YES
total18,759 / 18,759100%0034 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.78136
gson (195)0.57339
commons-lang3 (345)1.99173
jsoup (238)0.88270
snakeyaml (231)0.97237
spring-core (978)4.00244
fastjson2 (681)25.6427
guava (1,892)5.66334
total40.50115

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.

Head-to-head vs CFR & Vineflower

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.

−100%
fewer defective classes than CFR (0 vs 456) — JavaJive wins all 8 JARs
100%
clean-class rate — #1, ahead of Vineflower (90.8%) and CFR (79.8%)
1 of 3
the only pure-Go decompiler in the top tier — CFR and Vineflower are JVM apps

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%)
total0/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.

Features

Three Java building blocks, one portable module — plus the supporting cast trimmed down to a self-contained core.

Decompiler

Turn .class / .jar / .war / .zip into readable Java source, with whole-archive output that mirrors the original package layout.

Class parser

Inspect the full structure of a .class file — constant pool, fields, methods, version, and access flags.

Serialization

Parse and re-marshal the Java ObjectStream wire format with byte fidelity, and convert it losslessly to and from JSON.

Portable & pure Go

No JDK, no cgo, no ANTLR runtime. Cross-compiles to a single static binary for linux / macOS / windows on amd64 and arm64.

First-class CLI

decompile, classinfo, and serial subcommands built on the standard library — small, dependency-light, scriptable.

Cross-tested with a real JDK

CI compiles real .class / .jar and JDK-serialized blobs with javac/java, then verifies JavaJive against them.

Library quickstart

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...)