Skip to content

Instantly share code, notes, and snippets.

@thomasdarimont
Last active February 27, 2024 09:08
Show Gist options
  • Select an option

  • Save thomasdarimont/964c01ae3274eb0124af to your computer and use it in GitHub Desktop.

Select an option

Save thomasdarimont/964c01ae3274eb0124af to your computer and use it in GitHub Desktop.
How to work with binary diffs / patches of Java jars

How to do binary diffs with Java jars

This is a simple example how to generate and apply a binary patch to a jar file. In the hope that some tooling vendor or gradle / maven / repository backend guru might pick this up to unban us from too long dependency download times :)

Download test jars

For testing we download two versions of the commonly used google-guava library.

$ wget http://central.maven.org/maven2/com/google/guava/guava/18.0/guava-18.0.jar
$ wget http://central.maven.org/maven2/com/google/guava/guava/16.0.1/guava-16.0.1.jar

Obtain bsdiff / bspatch

http://www.daemonology.net/bsdiff/

#Create the binary patch file

$ bsdiff guava-16.0.1.jar guava-18.0.jar guava-16.0.1-18.0.patch

#List directory

$ ll
total 10520
-rw-r--r--  1 tom  staff   878K Mar 12 10:45 guava-16.0.1-18.0.patch
-rw-r--r--  1 tom  staff   2.1M Feb  3  2014 guava-16.0.1.jar
-rw-r--r--  1 tom  staff   2.2M Aug 25  2014 guava-18.0.jar

As one can see the binary patch file is around 900kb

#Rename the original jar file

$ mv guava-18.0.jar guava-18.0.jar.orig

#compute the MD5 hash of the original file

$ md5 guava-18.0.jar.orig

MD5 (guava-18.0.jar.orig) = 947641f6bb535b1d942d1bc387c45290

Apply the binary patch file

where guava-18.0.jar denotes the target file.

$ bspatch guava-16.0.1.jar guava-18.0.jar guava-16.0.1-18.0.patch

List the directory again

$ ll
total 14928
-rw-r--r--  1 tom  staff   878K Mar 12 10:45 guava-16.0.1-18.0.patch
-rw-r--r--  1 tom  staff   2.1M Feb  3  2014 guava-16.0.1.jar
-rw-r--r--  1 tom  staff   2.2M Mar 12 10:51 guava-18.0.jar
-rw-r--r--  1 tom  staff   2.2M Aug 25  2014 guava-18.0.jar.orig

#Compute the MD5 hash of the new file

$ md5 guava-18.0.jar
MD5 (guava-18.0.jar) = 947641f6bb535b1d942d1bc387c45290

As one can see the checksums match :)

I think it would be a nice feature and a huge bandwidth-saver if maven / gradle and the repository backends would support binary diffs for jars.

It could be as simple as ... I have version x ... I want to upgrade to x+4, please generate the diff and send it to me...

@Hrozhek
Copy link
Copy Markdown

Hrozhek commented Jun 2, 2021

Another approach is to open JAR files and build binary diffs for each entry inside JAR independently. This approach require some JAR patching mechanism (e.g. Java used to have JarDiffPatcher in JnlpDownloadServlet), but resulting patches are considerably less in size.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment