
Descompilador Java e Operador de Serialização em Go Puro
.zip.class (constant pool,
campos, métodos, versão, flags de acesso).Construído para portabilidade e incorporação:
javajive envolve as três
capacidades; os subpacotes permanecem disponíveis para uso avançado.decompile, classinfo e serial,
construídos sobre a biblioteca padrão..class / .jar reais e
blobs serializados pelo JDK com javac/java, depois verifica o JavaJive contra eles
(veja HARNESS-WORKFLOW.md).utils / codec / log / go-funk são
reimplementados como um núcleo internal/ mínimo e autocontido.A auditoria diferencial completa de 38 JARs registra zero regressões em relação à linha de base fixa: todos os 20 JARs anteriormente limpos de compilação são mantidos e 26 agora compilam integralmente. Defeitos da linha de base e 4 stubs de métodos existentes permanecem visíveis. Veja os resultados por JAR e reprodução.
250 round trips semânticos isolados registram compilação, verificação da JVM, stubs e igualdade em tempo de execução separadamente; as classes originais da aplicação estão ausentes dos classpaths reconstruídos. A CI executa a auditoria semântica no JDK 17 e 21, a comparação histórica completa, e as matrizes de OS/Go e de race. Essas verificações não provam equivalência de todos os métodos de biblioteca. Veja a implementação e limites restantes.
Os números a seguir foram reportados para a v0.3.0 em 2026-09-05. Eles não são resultados de aceitação da versão atual nem prova de equivalência comportamental.
Medido em 34 jars do mundo real (18.759 unidades achatadas) via decompile → recompilação com
javac --release 8 → reempacotamento → verificação da JVM:
Outer$Inner.java)
recompilam com zero erros de javac, e 0 erros de sintaxe em todos os 34 jars (uma asserção
rígida imposta pela CI, para que nenhum erro de tipo se esconda atrás de uma falha do lexer).-Xverify:all por classe passa de ponta a ponta (o codec é byte-idêntico ao
jar original sob um diferencial de chamadas). Fixado em provenClean.Veja BENCHMARK.md para a metodologia completa, tabelas por jar e comandos de reprodução.
# CLI
go install github.com/yaklang/javajive/cmd/javajive@latest
# Library
go get github.com/yaklang/javajive@latest
Ou compile a partir do código-fonte:
git clone https://github.com/yaklang/javajive
cd javajive
go build -o javajive ./cmd/javajive
Requer 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
Use o pacote de fachada unificado — uma importação cobre as três capacidades:
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...)
| Função | Propósito |
|---|---|
Decompile(classBytes) (string, error) | Descompila os bytes de um .class |
DecompileFile(path) (string, error) | Descompila um .class do disco |
DecompileWithResolver(classBytes, resolve) | Descompila com um resolvedor de bytes de classe |
DecompileArchive(src, dst) error | Descompila um .jar/.war/.zip em um diretório |
ParseClass(classBytes) (*ClassObject, error) | Analisa os bytes de um .class |
ParseClassFile(path) (*ClassObject, error) | Analisa um .class do disco |
ParseSerialized(raw) ([]JavaSerializable, error) | Analisa um fluxo de serialização |
ParseSerializedHex(hexStr) ([]JavaSerializable, error) | Analisa um fluxo codificado em hex |
MarshalSerialized(objs...) []byte | Recodifica objetos para o formato de transmissão |
MarshalSerializedHex(objs...) string | Recodifica para hex |
SerializedToJSON(objs...) ([]byte, error) | Converte objetos para JSON |
SerializedFromJSON(raw) ([]JavaSerializable, error) | Reconstrói objetos a partir de JSON |
Os subpacotes também são exportados para uso avançado:
classparser, classparser/jarwar, serialization.
Para permanecer portátil e pequeno, o JavaJive faz algumas escolhas deliberadas em relação ao yaklang. Veja MIGRATE.md para o mapeamento completo e o guia de migração.
| Área | yaklang (upstream) | JavaJive |
|---|---|---|
| Rede de segurança ANTLR do descompilador | revalida o código-fonte gerado via uma gramática Java ANTLR; degrada membros para stubs em caso de falha | removida (dependência pesada); a validação é um no-op, a saída é emitida diretamente |
Camada de suporte (utils / codec / log / go-funk) | pacotes compartilhados do monorepo | reimplementações mínimas e autocontidas sob internal/ |
Gerador de gadgets yso | incluído | não incluído |
Recuperação de charset de literais de string (MatchMIMEType) | recuperação opcional GBK/GB18030 | stub (no-op); comportamento inalterado para a grande maioria dos casos |
As dependências de terceiros estão confinadas a um pequeno conjunto de bibliotecas puras em Go
(gobwas/glob, go-viper/mapstructure, samber/lo, tidwall/gjson,
segmentio/ksuid, yeka/zip, e alguns 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)
Os testes cruzados com JDK compilam artefatos Java reais em tempo de teste e os verificam
contra o JavaJive; eles fazem t.Skip automaticamente quando não há JDK presente. Veja
HARNESS-WORKFLOW.md para saber como o harness e a CI funcionam.
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