
Decompilatore Java e operatore di serializzazione in puro Go
.zip.class (constant pool,
campi, metodi, versione, flag di accesso).Progettato per portabilità e integrazione:
javajive racchiude tutte e tre le
funzionalità; i sotto-pacchetti restano disponibili per usi avanzati.decompile, classinfo e serial,
basati sulla libreria standard..class / .jar reali e
blob serializzati dal JDK con javac/java, poi verifica JavaJive contro di essi
(vedi HARNESS-WORKFLOW.md).utils / codec / log / go-funk sono
reimplementati come un core internal/ minimale e autosufficiente.Il completo audit differenziale su 38 JAR registra zero regressioni rispetto alla baseline fissata: tutti i 20 JAR precedentemente compilabili senza errori sono mantenuti e 26 ora compilano completamente. I difetti della baseline e 4 stub di metodi esistenti restano visibili. Vedi i risultati per-JAR e la riproduzione.
250 round trip semantici isolati registrano separatamente compilazione, verifica JVM, stub e uguaglianza a runtime; le classi applicative originali sono assenti dai classpath ricostruiti. La CI esegue l'audit semantico su JDK 17 e 21, il confronto storico completo, e le matrici OS/Go e race. Questi controlli non provano l'equivalenza di ogni metodo di libreria. Vedi l'implementazione e i confini rimanenti.
Le seguenti cifre sono state riportate per la v0.3.0 il 2026-09-05. Non sono risultati di accettazione della versione corrente né prova di equivalenza comportamentale.
Misurati su 34 jar reali (18.759 unità appiattite) tramite decompile → ricompilazione con javac --release 8
→ repackage → verifica JVM:
Outer$Inner.java)
ricompilano con zero errori javac, e 0 errori di sintassi su tutti i 34 jar (un'asserzione
rigida imposta dalla CI, così nessun errore di tipo può nascondersi dietro un fallimento del lexer).-Xverify:all per-classe superata end-to-end (il codec è identico byte per byte al
jar originale sotto un differenziale di chiamate). Bloccato in provenClean.Vedi BENCHMARK.md per la metodologia completa, le tabelle per-jar e i comandi di riproduzione.
# CLI
go install github.com/yaklang/javajive/cmd/javajive@latest
# Library
go get github.com/yaklang/javajive@latest
Oppure compila dai sorgenti:
git clone https://github.com/yaklang/javajive
cd javajive
go build -o javajive ./cmd/javajive
Richiede Go 1.22+.
javajive <command> [arguments]
Commands:
decompile decompile .class/.jar/.war/.zip or a directory into Java source
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
# Directory: recursively decompile .class files (requires -o output dir).
javajive decompile ./classes -o ./src
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
Usa il pacchetto facade unificato — un solo import copre tutte e tre le funzionalità:
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...)
| Funzione | Scopo |
|---|---|
Decompile(classBytes) (string, error) | Decompila i byte di un .class |
DecompileFile(path) (string, error) | Decompila un .class dal disco |
DecompileWithResolver(classBytes, resolve) | Decompila con un resolver di byte di classe |
DecompileArchive(src, dst) error | Decompila un .jar/.war/.zip in una directory |
ParseClass(classBytes) (*ClassObject, error) | Analizza i byte di un .class |
ParseClassFile(path) (*ClassObject, error) | Analizza un .class dal disco |
ParseSerialized(raw) ([]JavaSerializable, error) | Analizza uno stream di serializzazione |
ParseSerializedHex(hexStr) ([]JavaSerializable, error) | Analizza uno stream codificato in hex |
MarshalSerialized(objs...) []byte | Ricodifica gli oggetti nel formato wire |
MarshalSerializedHex(objs...) string | Ricodifica in hex |
SerializedToJSON(objs...) ([]byte, error) | Converte gli oggetti in JSON |
SerializedFromJSON(raw) ([]JavaSerializable, error) | Ricostruisce gli oggetti dal JSON |
I sotto-pacchetti sono anch'essi esportati per usi avanzati:
classparser, classparser/jarwar, serialization.
Per restare portabile e compatto, JavaJive fa alcune scelte deliberate rispetto a yaklang. Vedi MIGRATE.md per la mappatura completa e la guida alla migrazione.
| Area | yaklang (upstream) | JavaJive |
|---|---|---|
| Rete di sicurezza ANTLR del decompilatore | rivalida il sorgente dumpato tramite una grammatica Java ANTLR; degrada i membri a stub in caso di fallimento | rimossa (dipendenza pesante); la validazione è un no-op, l'output è emesso direttamente |
Strato di supporto (utils / codec / log / go-funk) | pacchetti condivisi del monorepo | reimplementazioni minime e autosufficienti sotto internal/ |
Generatore di gadget yso | incluso | non incluso |
Recupero del charset dei letterali stringa (MatchMIMEType) | recupero opzionale GBK/GB18030 | stubbato (no-op); comportamento invariato per la stragrande maggioranza dei casi |
Le dipendenze di terze parti sono confinate a un piccolo insieme di librerie in puro Go
(gobwas/glob, go-viper/mapstructure, samber/lo, tidwall/gjson,
segmentio/ksuid, yeka/zip, e alcune golang.org/x/*).
go test ./... # unit tests + JDK cross-tests (skipped if no JDK)
go test ./... -race # data-race free (linux)
go test ./test/cross/ -v # Java cross-tests only (needs javac/java on PATH)
I cross-test JDK compilano artefatti Java reali al momento del test e li verificano
contro JavaJive; eseguono automaticamente t.Skip quando nessun JDK è presente. Vedi
HARNESS-WORKFLOW.md per come funzionano l'harness e la CI.
javajive.go unified facade package (import "github.com/yaklang/javajive")
serialization/ Java serialization/deserialization (from yaklang common/yserx)
classparser/ class parser + decompiler (from yaklang common/javaclassparser)
cmd/javajive/ CLI entry point
internal/ trimmed self-contained support layer (log / codec / funk / utils / filesys / ...)
test/cross/ JDK-backed cross-tests (javac/java)
site/ static landing page deployed to GitHub Pages