
Pure-Go Java デコンパイラおよびシリアライゼーション演算子
.war.zip.classファイルの構造(定数プール、フィールド、メソッド、バージョン、アクセスフラグ)を検査。ポータビリティと組み込みを目的として設計:
javajiveファサードパッケージが3つの機能すべてをラップ。高度な用途向けにサブパッケージも利用可能。decompile、classinfo、serialサブコマンドを標準ライブラリ上に構築。javac/javaで実際の.class / .jarおよびJDKシリアライズ済みブロブをコンパイルし、JavaJiveをそれらに対して検証します(HARNESS-WORKFLOW.md参照)。utils / codec / log / go-funkは最小限で自己完結したinternal/コアとして再実装。完全な38-JAR差分監査は、固定ベースラインに対して記録されたリグレッションがゼロであることを示しています:以前コンパイルがクリーンだった20個のJARはすべて維持され、26個が完全にコンパイルされるようになりました。ベースラインの欠陥と4つの既存メソッドスタブは引き続き可視化されています。JARごとの結果と再現方法を参照してください。
250件の分離されたセマンティックラウンドトリップは、コンパイル、JVM検証、スタブ、ランタイム等価性を個別に記録します。元のアプリケーションクラスは再構築されたクラスパスに存在しません。CIはJDK 17と21でセマンティック監査、完全な履歴比較、OS/Goおよびレースマトリクスを実行します。これらのチェックはすべてのライブラリメソッドの等価性を証明するものではありません。実装と残された境界を参照してください。
以下の数値は2026-09-05にv0.3.0について報告されたものです。これらは現行バージョンの受け入れ結果でも、動作等価性の証明でもありません。
34個の実世界のjar(18,759個のフラット化ユニット)に対して、デコンパイル → javac --release 8再コンパイル → 再パッケージ → JVM検証で測定:
Outer$Inner.java)が**javacエラーゼロで再コンパイルされ、34個のjarすべてで構文エラー0件**(CIで強制されるハードアサーションのため、字句解析の失敗の陰に型エラーが隠れることはありません)。-Xverify:allによるクラスごとの検証がエンドツーエンドで成功(コーデックは呼び出し差分において元のjarとバイト単位で同一)。provenCleanに固定。完全な方法論、jarごとの表、再現コマンドについてはBENCHMARK.mdを参照してください。
# CLI
go install github.com/yaklang/javajive/cmd/javajive@latest
# Library
go get github.com/yaklang/javajive@latest
またはソースからビルド:
git clone https://github.com/yaklang/javajive
cd javajive
go build -o javajive ./cmd/javajive
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
統一ファサードパッケージを使用してください — 1つのインポートで3つの機能すべてをカバーします:
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...)
| 関数 | 目的 |
|---|---|
Decompile(classBytes) (string, error) | 1つの.classのバイト列をデコンパイル |
DecompileFile(path) (string, error) | ディスクから1つの.classをデコンパイル |
DecompileWithResolver(classBytes, resolve) | クラスバイト列リゾルバを使用してデコンパイル |
DecompileArchive(src, dst) error | .jar/.war/.zipをディレクトリにデコンパイル |
ParseClass(classBytes) (*ClassObject, error) | 1つの.classのバイト列をパース |
ParseClassFile(path) (*ClassObject, error) | ディスクから1つの.classをパース |
ParseSerialized(raw) ([]JavaSerializable, error) | シリアライゼーションストリームをパース |
ParseSerializedHex(hexStr) ([]JavaSerializable, error) | 16進エンコードされたストリームをパース |
MarshalSerialized(objs...) []byte | オブジェクトをワイヤフォーマットに再エンコード |
MarshalSerializedHex(objs...) string | 16進に再エンコード |
SerializedToJSON(objs...) ([]byte, error) | オブジェクトをJSONに変換 |
SerializedFromJSON(raw) ([]JavaSerializable, error) | JSONからオブジェクトを再構築 |
サブパッケージも高度な用途向けにエクスポートされています:
classparser、classparser/jarwar、serialization。
ポータブルかつ小さく保つため、JavaJiveはyaklangに対していくつかの意図的なトレードオフを行っています。完全なマッピングと移行ガイドについてはMIGRATE.mdを参照してください。
| 領域 | yaklang(上流) | JavaJive |
|---|---|---|
| デコンパイラのANTLRセーフティネット | ANTLR Java文法を介してダンプされたソースを再検証;失敗時はメンバーをスタブに降格 | 削除(重い依存関係);検証はノーオペレーションで、出力は直接生成される |
サポート層(utils / codec / log / go-funk) | 共有モノレポパッケージ | internal/配下の最小限で自己完結した再実装 |
ysoガジェットジェネレータ | 含まれる | 含まれない |
文字列リテラルの文字集合復元(MatchMIMEType) | オプションのGBK/GB18030復元 | スタブ化(ノーオペレーション);大多数のケースで動作は不変 |
サードパーティ依存は少数の純粋Goライブラリに限定されています
(gobwas/glob、go-viper/mapstructure、samber/lo、tidwall/gjson、
segmentio/ksuid、yeka/zip、およびいくつかの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)
JDKクロステストはテスト時に実際のJavaアーティファクトをコンパイルし、JavaJiveに対して検証します。JDKが存在しない場合は自動的にt.Skipします。ハーネスとCIの仕組みについてはHARNESS-WORKFLOW.mdを参照してください。
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