Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Packaging ONLY the necessary Classes from Dependencies

How can I use the maven shade or assembly plugin to automatically determine which classes are needed from the dependency jars, and copy ONLY these classes into the build. So far I have had no luck getting it to automatically find which classes will be necessary for my build.

I can use minimizeJar and include and exclude tags to specify which classes get added but what I really want it to do is something like this:

Copy all of the imports of all of my classes into the jar, and copy all of their imports, and all of their import's imports and so on.

Am I thinking about the problem all wrong? How can I get maven to automatically minimize the jar size depending on which imports are used? (please don't just say this maven plugin) because I am already at a dead end, I need an example of what to add to my pom to accomplish these tasks.

like image 835
Supercreature Avatar asked Jun 04 '15 23:06

Supercreature


1 Answers

ProGuard can remove unused classes and even more.

ProGuard is a free Java class file shrinker, optimizer, obfuscator, and preverifier. It detects and removes unused classes, fields, methods, and attributes. It optimizes bytecode and removes unused instructions. It renames the remaining classes, fields, and methods using short meaningless names.

First, you should package a jar with dependencies. It can be easily done with maven-assembly-plugin:

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>2.5.4</version>
    <configuration>
        <archive>
            <manifest>
                <mainClass>com.test.HelloWorld</mainClass>
            </manifest>
        </archive>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
    </configuration>
    <executions>
        <execution>
            <id>make-assembly</id> 
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Then configure proguard to optimize generated jar. For maven projects, use proguard-maven-plugin:

<plugin>
    <groupId>com.github.wvengen</groupId>
    <artifactId>proguard-maven-plugin</artifactId>
    <version>2.0.10</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals><goal>proguard</goal></goals>
        </execution>
    </executions>
    <configuration>        
        <injar>${project.build.finalName}-jar-with-dependencies.jar</injar>
        <outjar>${project.build.finalName}-small.jar</outjar>
        <outputDirectory>${project.build.directory}</outputDirectory>
        <options>
            <option>-dontobfuscate</option>
            <option>-dontwarn com.google.**</option>
            <option>-keep public class com.test.HelloWorld {public static void main(java.lang.String[]);}</option>
        </options>
        <libs>
            <lib>${java.home}/lib/rt.jar</lib>
        </libs>
    </configuration>
</plugin>

After these steps run

mvn clean install

and check target/<artifact name>-small.jar - it should contain only classes that are actually used in runtime.

Please note that there might be some issues if your code or your dependencies use reflection.

like image 50
Kostiantyn Avatar answered Nov 15 '22 01:11

Kostiantyn