Jar file size optimiser.
JarTighten is a jar file size optimiser, including optimisations based on quirks of Java's zip parsing implementation. Although JarTighten is intended to be run as the final step in the optimisation pipeline (after deflate optimisation), it does include options for recompressing files with CafeUndZopfli.
JarTighten is available as a command line program:
Usage: JarTighten [-bcdDEhijJlLMnorRsStVxzZ] [--compare-size-bits]
[--optimise-existing-streams]
[--optimise-recompressed-streams]
[-I=<recompressZopfliPasses>] [-m=<mode>] [-e=<filename>]...
<inputFile> <outputFile>
Jar file size optimiser
<inputFile> The file to optimise
<outputFile> The optimised file
-b, --merge-blocks Try merging deflate blocks. May majorly increase
time spent optimising files.
-c, --remove-comments Remove file comments and zip comment
--compare-size-bits Compare sizes of deflate streams in bits instead
of bytes. Majorly increases time spent
optimising files.
-d, --[no-]remove-directory-entries
Remove directory entries
-D, --deduplicate-entries Deduplicate local file header entries with the
same compressed contents
-e, --exclude=<filename> Files to exclude from optimisations which might
hide them from standard zip libraries
-E, --remove-extra Remove extra field
-h, --help Show this help message and exit.
-i, --remove-eocd-info Remove EOCD info
-I, --iter, --zopfli-iter=<recompressZopfliPasses>
Zopfli iterations. More iterations increases time
spent optimising files.
-j, --recompress-jzopfli Recompress files with jzopfli, uses compressed
output if smaller
-J, --[no-]recompress-jzlib
Recompress files with JZlib, uses compressed
output if smaller
-l, --remove-file-length Remove file length from local file headers
-L, --remove-dir-entry-length
Remove file length from central directory entries
-m, --mode=<mode> Determines which compression strategies are run
for each compressor. Improves compression at the
cost of running each selected compressor
multiple times. Valid values: SINGLE,
MULTI_CHEAP, EXTENSIVE
-M, --[no-]recompress-multithread
Run each compressor in a separate thread. May
improve performance.
-n, --remove-file-names Remove file names from local file headers
-o, --overwrite Overwrite existing output file
--optimise-existing-streams
Optimise existing deflate streams. Majorly
increases time spent optimising files.
--optimise-recompressed-streams
Optimise recompressed deflate streams. Majorly
increases time spent optimising files.
-r, --[no-]recompress-standard
Recompress files with standard Java deflate
implementation, uses compressed output if smaller
-R, --recursive-store Store the contents of all embedded zip or jar
files uncompressed recursively and compress,
uses compressed output if smaller
-s, --[no-]recompress-store
Check uncompressed size, stores uncompressed if
smaller
-S, --sort-entries Sort zip entries in the way they're expected to be
in a jar file
-t, --remove-timestamps Remove timestamps
-V, --version Print version information and exit.
-x, --make-exec, --make-executable-jar
Mark the output jar file as executable on certain
operating systems if not already set. Increases
file size by 4 bytes.
-z, --recompress-zopfli Recompress files with CafeUndZopfli, uses
compressed output if smaller
-Z, --zero-local-file-headers
Replace every value that the JVM doesn't read in
local file headers with zeros. Overrides other
options.
A Gradle plugin with equivalent options is also available on the Gradle Plugin Portal:
plugins {
id 'io.github.nerdthened.jartighten' version '1.2.+'
}
jartighten {
// By default, JarTighten will optimise the output of the jar task.
//inputFile = layout.projectDirectory.file(...)
//outputFile = layout.projectDirectory.file(...)
// Remove file timestamps
removeTimestamps = true
// Remove local header file length
//removeFileLength = true
// Remove central directory entry file length
//removeDirEntryLength = true
// Remove local header file names
//removeFileNames = true
// Remove end of central directory info
//removeEOCDInfo = true
// Remove file commments and zip comment
removeComments = true
// Remove extra field
removeExtra = true
// Remove directory entries
removeDirectoryEntries = true
// Deduplicate local file header entries with the same compressed contents
//deduplicateEntries = true
// Enable CafeUndZopfli recompression (very time consuming, may require configuring Gradle to use more memory)
recompressZopfli = true
// Enable jzopfli recompression (very time consuming, may require configuring Gradle to use more memory)
//recompressJZopfli = true
// Zopfli iterations. More iterations increases time spent optimising files.
//recompressZopfliPasses = 20
// Disable JZlib recompression (enabled by default)
//recompressJZlib = false
// Disable standard JVM deflate recompression (enabled by default)
//recompressStandard = false
// Disable checking if storing a file as uncompressed would be smaller (enabled by default)
//recompressStore = false
// Disable running each compressor in a separate thread
//recompressMultithread = false
// Determines which compression strategies are run for each compressor.
// Improves compression at the cost of running each selected compressor multiple times.
// Valid values: SINGLE, MULTI_CHEAP, EXTENSIVE
//mode = 'EXTENSIVE'
// Store the contents of all embedded zip or jar files uncompressed recursively and compress, uses compressed output if smaller
recursiveStore = true
// Sort zip entries in the way they're expected to be in a jar file
sortEntries = true
// Zero all metadata that the JVM doesn't read. Overrides other options.
//zeroLocalFileHeaders = true
// Optimise existing deflate streams with deft4j. Majorly increases time spent optimising files.
//optimiseDeflateStreamExisting = true
// Optimise recompressed deflate streams with deft4j. Majorly increases time spent optimising files.
//optimiseDeflateStreamRecompress = true
// Compare sizes of deflate streams in bits instead of bytes. Majorly increases time spent optimising files.
//compareDeflateStreamBits = true
// Mark the output jar file as executable on certain operating systems if not already set. Increases file size by 4 bytes.
//makeExecutableJar = true
// Try merging deflate blocks. May majorly increase time spent optimising files.
//mergeBlocks = true
// Exclude a file from optimisations which might hide them from standard zip libraries
//excludes = ["some/package/SomeFile.ext"]
}
build.finalizedBy(jartighten)
// You can also create custom JarTighten tasks:
import io.github.NeRdTheNed.JarTighten.JarTightenTask
tasks.register('jartightenCustom', JarTightenTask) {
// Set the input and output files
inputFile = layout.projectDirectory.file(...)
outputFile = layout.projectDirectory.file(...)
// Configure task etc
}
build.finalizedBy(jartightenCustom)