
Pure-Go Java Decompiler and Serialization Operator
A portable, pure-Go Java toolkit — extracted and trimmed from yaklang — focused on four things:
.class / .jar / .war / .zip → readable Java source..dex / .apk → deterministic .jar, or directly
to readable Java source, without invoking an external dex2jar tool..class file (constant pool,
fields, methods, version, access flags).Built for portability and embedding:
javajive facade package wraps all four
capabilities; the sub-packages remain available for advanced use.decompile, dex2jar, classinfo, and serial
subcommands, built on the standard library..class / .jar and
JDK-serialized blobs with javac/java, then verifies JavaJive against them
(see HARNESS-WORKFLOW.md).utils / codec / log / go-funk are
reimplemented as a minimal, self-contained internal/ core.The complete 38-JAR differential audit reports zero recorded regressions against the fixed baseline: all 20 previously compile-clean JARs are retained and 26 now compile in full. Baseline defects and 4 existing method stubs remain visible. See the per-JAR results and reproduction.
250 isolated semantic round trips record compilation, JVM verification, stubs and runtime equality separately; original application classes are absent from rebuilt classpaths. CI runs the semantic audit on JDK 17 and 21, the full historical comparison, and the OS/Go and race matrices. These checks do not prove equivalence of every library method. See the implementation and remaining boundaries.
The following figures were reported for v0.3.0 on 2026-09-05. They are not current-version acceptance results or proof of behavioral equivalence.
Measured on 34 real-world jars (18,759 flattened units) via decompile → javac --release 8
recompile → repackage → JVM verify:
Outer$Inner.java)
recompile with zero javac errors, and 0 syntax errors across all 34 jars (a CI-enforced
hard assertion, so no type error can hide behind a lexer failure).-Xverify:all per-class verification passes end-to-end (codec is byte-identical to the
original jar under a call differential). Locked in provenClean.See BENCHMARK.md for the full methodology, per-jar tables and reproduction commands.
# CLI
go install github.com/yaklang/javajive/cmd/javajive@latest
# Library
go get github.com/yaklang/javajive@latest
Or build from source:
git clone https://github.com/yaklang/javajive
cd javajive
go build -o javajive ./cmd/javajive
Requires Go 1.22+.
javajive <command> [arguments]
Commands:
decompile decompile Java artifacts or the strict DEX 035 subset into Java source
dex2jar convert the strict DEX 035 subset in a DEX/APK to a deterministic JAR
classinfo print the structure of a .class file (version, fields, methods)
serial Java serialization tools (subcommands: tojson, fromjson)
version print the version
help show help
# Single class: prints to stdout by default, or -o to write a file.
javajive decompile Foo.class
javajive decompile Foo.class -o Foo.java
# Archive: defaults to a "<input>.src" directory, or -o to choose one.
javajive decompile app.jar
javajive decompile app.war -o ./app-src
# DEX or APK: run the native DEX-to-JAR pipeline and decompile the result.
# The default output directory is "<input>.src".
javajive decompile classes.dex
javajive decompile app.apk -o ./app-src
# Directory: recursively decompile .class files (requires -o output dir).
javajive decompile ./classes -o ./src
javajive dex2jar -o classes.jar classes.dex
javajive dex2jar -o app.jar app.apk
Input is detected by magic rather than the filename extension. Output is a
reproducible JAR. dex2jar fails the complete conversion on any unsupported or
malformed class or method; it writes a same-directory temporary file before
replacing the destination and never substitutes method stubs.
Native DEX translation is currently a strict first vertical slice, not a
general Android application converter. The tested subset is standard DEX 035
with ordinary integer/reference control flow, fields and invokes, safely paired
new-instance/constructor initialization, and basic arrays. Generated class
files are parser-tested and JVM-verified, including executable branch, field,
invoke, constructor, and int[] paths.
Not yet supported: try/catch and monitor operations; float, long, and double
values or opcodes; switches, payload instructions, and filled arrays; DEX 038+
dynamic invokes and method constants; annotations and debug metadata;
CompactDex; and APK resources or native libraries. APK input means only
canonically named classes.dex, classes2.dex, ... entries are translated.
All selected DEX files must succeed transactionally or no JAR is produced.
javajive classinfo Foo.class
class: InvisibleAnnoSeed
super: java/lang/Object
version: 61.0
access: public
constants: 18
fields (0):
methods (2):
<init>()V
run()I
# Serialized binary -> JSON. (-hex: input is a hex string, -: read from stdin)
javajive serial tojson dump.bin
printf 'aced000574000568656c6c6f' | javajive serial tojson -hex -
# JSON -> serialized binary. (default prints hex; with -o writes raw bytes)
javajive serial fromjson dump.json -o out.bin
javajive serial fromjson dump.json # prints hex