Jardiff is a command-line tool for comparing the contents of JAR files and directories. It provides detailed, line-based diffs of class files and resources, making it easy to spot changes between builds, releases, or different versions of Java/Kotlin projects.
Note
This project is not affiliated with Lightbend or the original jardiff project.
While lightbend-labs/jardiff and this tool share the same name and similar goals, they have different features:
The lightbend-labs/jardiff focuses on Scala projects, and it has some useful flags to tweak the bytecode output (ordering, suppress private members). This tool also has a mode to create a git repository to leverage git diff capabilities.
However, bric3/jardiff offers a more versatile tooling to inspect class differences
- Additional to the usual diff output, it provides statistics (
--stat) and status (--status) modes similar to git diff/status - Supports class extension coalescing, in case classes are renamed to other extensions like
.bin,.clazz, etc. - Various text representation modes for class files
- Flexible glob pattern filtering for including/excluding files
- Offers limited support for non-binary text files
Example output in default mode:
--- foo/bar/qux/Baz.class
+++ foo/bar/qux/Baz.class
@@ -6,1548 +6,17 @@
// access flags 0x9
public static create()Lfoo/bar/ZuulMatcher;
NEW foo/bar/ZuulMatcher
DUP
- LDC 15
+ LDC 3
ANEWARRAY foo/bar/Zuul
DUP
LDC 0
NEW foo/bar/Zuul
DUP
- LDC 14
- ANEWARRAY java/lang/String
- DUP
LDC 0
- LDC "foo.bar.qux.T:18"
- AASTORE
- DUP
- LDC 1
- LDC "foo.bar.qux.U:33"
- AASTORE
- DUP
- LDC 2
- LDC "foo.bar.qux.V:49"
- AASTORE
- DUP
- LDC 3
- LDC "foo.bar.qux.W:68"
- AASTORE
- DUP
...
+ LDC 2
NEW foo/bar/Zuul
DUP
LDC 0
ANEWARRAY java/lang/StringOr with the --status mode
D foo/bar/qux/Zuul.class
D foo/bar/qux/Zig.class
M foo/bar/qux/Baz.class
Or with the --stat mode
foo/bar/qux/Zuul.class | 42 ++++++++++++++++++++++++++++++++----------
foo/bar/qux/Zig.class | 1 -
foo/bar/qux/Baz.class | 34 ++++++++++++++++++++++------------
3 files changed, 54 insertions(+), 23 deletions(-)
With class extension coalescing, paths with different left and right extensions use a Git-style brace form:
M foo/bar/qux/Baz{.class => .classdata}
When output piped to delta, it looks like this:
Other tools didn't have the feature I wanted, or they were impractical to use, so I made my own.
- Compare JARs and directories recursively
- Line-based diffs for each files
- Class file comparison using different strategy to produce text
- Auto-detects class files from their bytecode header, even without a
.classextension - ASM's Textify (default)
- Class outline (version, is kotlin/groovy class, synthetic or bridge members)
- Class File Version only
- Auto-detects class files from their bytecode header, even without a
- Binary diff as sha-1 hashes
- Include glob patterns (for the relative paths inside the jars/directories)
- Exclude glob patterns (for the relative paths inside the jars/directories)
- Optional class member order normalization
- Supports
--exit-codefor CI/CD pipelines
Features planned for future releases... :
- Ignoring debug information in class files (like line numbers, local variable names, etc.)
- Append Koltin/Scala/Groovy detection to regular class text output
- Replace ASM by the Class file API (Need JDK 24+)
- Better terminal integration, ideas: pager support, colors configuration, auto-detection of
delta, etc. (Might need FFM, need JDK 22+)
Caution
This tool needs a JDK11 to build and run. Example with mise
$ mise exec java@corretto-11 -- java -jar jardiff-0.1.0-SNAPSHOT.jarTip
The jar on the Github release is an executable jar, so you can run it directly with ./jardiff-0.1.0-SNAPSHOT.jar {left} {right} after downloading it (chmoding it executable as needed).
Build it ./gradlew build, then run it:
$ jardiff --help
Usage: jardiff [-hVv] [--exit-code] [--class-text-producer=<tool>]
[--color=<when>] [-c=<extension>[,<extension>...]]... [-e=<glob>
[,<glob>...]]... [-i=<glob>[,<glob>...]]... [--status | --stat]
<left> <right>
Compares two JAR files or directories and reports differences.
<left> The JAR file or directory to compare.
<right> The JAR file or directory to compare.
-c, --class-exts, --coalesce-classe-exts=<extension>[,<extension>...]
Coalesce class files with the given extensions, in
addition to the usual 'class', i.e. makes classes
named 'Foo.class' and 'Foo.bin' aliased to the same
file entry. Class files are auto-detected from their
bytecode header. Takes a comma separated list, e.g.
'classdata' or 'raw,bin,clazz'.
--class-text-producer=<tool>
Tool used to produce class text, possible values:
asm-textifier, class-file-version, class-outline, jcod,
javap
The javap producer uses the JDK running jardiff,
so output can vary by JDK version/vendor and
requires a JDK containing jdk.jdeps.
Default: 'asm-textifier'
--color=<when> Control when to use color output:
always, auto, never
Default: 'auto'
-e, --exclude=<glob>[,<glob>...]
Glob exclude patterns (comma separated), e.g.
'**/raw*/**', or '**/*.bin'.
--exit-code Make jardiff exit with codes similar to diff(1).
That is, it exits with 1 if there were differences
and 0 means no differences.
-h, --help Show this help message and exit.
--ignore-member-order
Ignore class member declaration order when
comparing class files.
-i, --include=<glob>[,<glob>...]
Glob include patterns (comma separated), e.g.
'**/raw*/**', or '**/*.bin'.
--stat Show statistics output (like 'git diff --stat').
Displays file-by-file statistics with
additions/deletions.
--status Show short status output (like 'git status --short').
Displays two-column XY status for changed files.
-v Specify multiple -v options to increase verbosity.
For example, '-v -v' or '-vv'.
-V, --version Print version information and exit.Tip
Use shell features, e.g. in Bash, ZSH instead of typing twice long folders use the brace expansion :
$ java -jar jardiff-0.1.0-SNAPSHOT.jar /Users/brice.dutheil/path/to/repositories/project{-original,-with-changes}/submodule/submodule/submodule/build/classes/java/mainAlso, you can run it from Gradle:
$ ./gradlew run --args="{left} {right}"{left}and{right}can be paths to JAR files or directories.- The tool outputs a summary and detailed diff of all differing files.
To build the project:
$ ./gradlew build- Kotlin
- Picocli
- ASM
- java-diff-utils
- Byte Buddy
- Apache Tika (for charset detection)
Copyright 2025 Brice Dutheil
Unless otherwise noted, all components are licenced under the Mozilla Public License Version 2.0.