I'm trying to generate two different jars from a project which is a monorepo that includes dependencies to many many great things in this world, so needless to say i do not want these executable jars to have big sizes and would rather have them include only classes that they actually use.
I followed instructions here https://imperceptiblethoughts.com/shadow/configuration/minimizing/
.
In order to test if shadowJar
task actually works i created a simple Main java file that practically uses nothing other than java SDK.
public class Main {
public static void main(String[] args) {
System.out.println("client");
}
}
and added the actual shadow jar task and pointed to this as a main class
shadowJar {
archiveBaseName.set('client')
archiveClassifier.set('')
archiveVersion.set('0.1')
minimize()
manifest {
attributes 'Main-Class': 'my.package.Main'
}
}
which generates the uber jar correctly (i was able to run it simply with java -jar ...
), however the size of the file is 10Mb.
then i generated a new version without minimize()
part and it was 15Mb.
Is there something i do wrong here? Maybe i'm expecting too much from this tool and proguard (as tedious as it is to setup) is the only way?
Since you did not provide us with your build file I can only give some general advice:
Main
class is the only file in the source tree (shadow does not care what the main class is)api
As you have stated yourself, the minimizing works. I also did some tests myself (see below) with many dependencies. The jar file was at 187MB without minimizing and had so many entries I needed to enable zip64. Shadow minimized it to just 25MB.
Now, where do those 25MB come from? From what I have seen in my testing there are two types of files that stay:
META-INF
folder was at 24MB in my test case)package-info.class
and module-info.class
(though there size is probably far less)Those can not be stripped automatically since it is unclear whether they are used or not.
If you are 100% sure you do not need some of those files you could filter them out from your jar manually. Although I doubt that it is worth the effort.
If you think there are other files included as well, you could extract the Jar (a jar is just a zip with a different name extension) and look at its content.
First off, I cloned Spring Boot, then I removed all unnecessary modules (that is everything except spring-boot-project:spring-boot
, spring-boot-project:spring-boot-dependencies
and spring-boot-project:spring-boot-parent
) and changed all dependencies of spring-boot-project:spring-boot
to be of type implementation
.
Then I removed the current source code and replaced it with your sample Main
class.
After adding the shadow
plugin I got a jar with a size of 187MB. When I then applied minimize
it was only 25MB.
I then extracted the Jar and ran some commands to remove every package-info
, module-info
and general resource file:
$> find \( \( -not -name "*.class" -or -name "package-info.class" -or -name "module-info.class" \) -and -not -type d \) -delete
$> find -empty -delete
I do not know if there is an equivalent command on Windows. In any case, doing the above leaves only a few number of class files left (144kB!), so I think it is save to say that shadow is doing its job.