Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ProGuard doesn't obfuscate JAR with dependencies

I have a project with the pom.xml file given below. When I issue the command mvn clean compile assembly:single install I want Maven to generate a JAR, which contains

  • all the dependencies and
  • obfuscated version of my code.

It doesn't work - my code is not obfuscated in the "jar-with-dependencies" file.

When I run mvn clean compile install the resulting file contains obfuscated code of my application, but no dependencies.

What can I do in order to have a JAR file with all the dependencies and my obfuscated code?

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mycompany</groupId>
    <artifactId>myproduct</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <properties>
        <restlet-version>2.3.5</restlet-version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.spongepowered</groupId>
            <artifactId>spongeapi</artifactId>
            <version>3.0.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.easytesting</groupId>
            <artifactId>fest-assert-core</artifactId>
            <version>2.0M8</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>1.10.19</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.restlet.jse</groupId>
            <artifactId>org.restlet</artifactId>
            <version>${restlet-version}</version>
        </dependency>
        <dependency>
            <groupId>org.restlet.jse</groupId>
            <artifactId>org.restlet.ext.jackson</artifactId>
            <version>${restlet-version}</version>
        </dependency>
        <dependency>
            <groupId>com.googlecode.json-simple</groupId>
            <artifactId>json-simple</artifactId>
            <version>1.1.1</version>
        </dependency>
    </dependencies>
    <build>
        <resources>
            <resource>
                <directory>${project.basedir}/src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>templating-maven-plugin</artifactId>
                <version>1.0-alpha-3</version>
                <executions>
                    <execution>
                        <id>filter-src</id>
                        <goals>
                            <goal>filter-sources</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
            </plugin>
            <plugin>
                <groupId>com.github.wvengen</groupId>
                <artifactId>proguard-maven-plugin</artifactId>
                <version>2.0.8</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals><goal>proguard</goal></goals>
                    </execution>
                </executions>
                <configuration>
                    <proguardVersion>5.2</proguardVersion>
                    <options>
                        <option>-allowaccessmodification</option>
                        <option>-dontoptimize</option>
                        <option>-dontshrink</option>
                        <option>-dontnote</option>
                        <option>-keepattributes Signature</option>
                        <option>-keep class com.mycompany.MyPlugin { *; }</option>
                    </options>
                    <libs>
                        <lib>${java.home}/lib/rt.jar</lib>
                    </libs>
                    <dependencies>
                        <dependency>
                            <groupId>net.sf.proguard</groupId>
                            <artifactId>proguard-base</artifactId>
                            <version>5.2</version>
                            <scope>runtime</scope>
                        </dependency>
                    </dependencies>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Update 1 (17.01.2016 19:54 MSK): Changed the ProGuard configuration like shown below, but mvn clean compile assembly:single still produces a JAR with unobfuscated class files.

<plugin>
    <groupId>com.github.wvengen</groupId>
    <artifactId>proguard-maven-plugin</artifactId>
    <version>2.0.8</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals><goal>proguard</goal></goals>
        </execution>
    </executions>
    <configuration>
        <proguardVersion>5.2</proguardVersion>
        <options>
            <option>-allowaccessmodification</option>
            <option>-dontoptimize</option>
            <option>-dontshrink</option>
            <option>-dontnote</option>
            <option>-keepattributes Signature</option>
            <option>-keep class com.mycompany.MyPlugin { *; }</option>
        </options>
        <injar>${project.build.finalName}-jar-with-dependencies.jar</injar>
        <libs>
            <lib>${java.home}/lib/rt.jar</lib>
        </libs>
        <dependencies>
            <dependency>
                <groupId>net.sf.proguard</groupId>
                <artifactId>proguard-base</artifactId>
                <version>5.2</version>
                <scope>runtime</scope>
            </dependency>
        </dependencies>
    </configuration>
</plugin>

Update 2 (17.01.2016 20:29 MSK): mvn clean compile assembly:single install fails. The last messages can be seen here.

like image 575
Dmitrii Pisarenko Avatar asked Jan 17 '16 12:01

Dmitrii Pisarenko


1 Answers

proguard-maven-plugin will obfuscate the primary artifact of your project, not the secondary artifact jar-with-dependencies that the maven-assembly-plugin generated.

You need to configure the plugin to obfuscate the jar-with-dependencies by specifying the injar attribute:

Specifies the input jar name (or wars, ears, zips) of the application to be processed.

<injar>${project.build.finalName}-jar-with-dependencies.jar</injar>

Now, there is also a problem in the order of execution of plugins in your POM: we need to make sure that the maven-assembly-plugin is executed before the proguard-maven-plugin. As such, it is best to define an explicit execution for the maven-assembly-plugin bound to the package phase instead of manually invoking it from the command line with assembly:single. This would be the configuration:

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <executions>
        <execution>
            <id>assembly</id>
            <goals>
                <goal>single</goal>
            </goals>
            <phase>package</phase>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
        </execution>
    </executions>
</plugin>

and then, you just need to make sure that the proguard-maven-plugin plugin configuration is after that in your POM.

Having done that, invoking Maven with mvn clean install will result in an obfuscated jar with dependencies.


To test with your actual POM, I added two repositories:

  • https://repo.spongepowered.org/maven to resolve the spongeapi dependency.
  • http://maven.restlet.com to resolve the org.restlet.jse dependencies.

With those 2 dependencies, warnings were generated by ProGuard because the org.restlet.ext.jackson dependency utilizes com.sun.msv.* classes that are not on the buildpath. Since I figure that your code is currently working, it means those classes don't need to be included and that those warnings can be ignored. As such, I added the -dontwarn option so that ProGuard doesn't error when there is a warning.

The final POM for which I was able to successfully obfuscate the jar with dependencies is the following:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mycompany</groupId>
    <artifactId>myproduct</artifactId>
    <version>1.0-SNAPSHOT</version>
    <repositories>
       <repository>
           <id>spongepowered</id>
           <url>https://repo.spongepowered.org/maven</url>
       </repository>
       <repository>
           <id>restlet</id>
           <url>http://maven.restlet.com</url>
       </repository>
    </repositories>
    <properties>
        <restlet-version>2.3.5</restlet-version>
    </properties>
    <build>
       <resources>
            <resource>
                <directory>${project.basedir}/src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>templating-maven-plugin</artifactId>
                <version>1.0-alpha-3</version>
                <executions>
                    <execution>
                        <id>filter-src</id>
                        <goals>
                            <goal>filter-sources</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <executions>
                    <execution>
                        <id>assembly</id>
                        <goals>
                            <goal>single</goal>
                        </goals>
                        <phase>package</phase>
                        <configuration>
                            <descriptorRefs>
                                <descriptorRef>jar-with-dependencies</descriptorRef>
                            </descriptorRefs>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>com.github.wvengen</groupId>
                <artifactId>proguard-maven-plugin</artifactId>
                <version>2.0.8</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals><goal>proguard</goal></goals>
                        <configuration>
                            <injar>${project.build.finalName}-jar-with-dependencies.jar</injar> <!-- make sure to obfuscate the jar with dependencies -->
                            <proguardVersion>5.2</proguardVersion>
                            <options>
                                <option>-allowaccessmodification</option>
                                <option>-dontoptimize</option>
                                <option>-dontshrink</option>
                                <option>-dontnote</option>
                                <option>-dontwarn</option> <!-- added option to ignore com.sun missing classes -->
                                <option>-keepattributes Signature</option>
                                <option>-keep class com.mycompany.MyPlugin { *; }</option>
                            </options>
                            <libs>
                                <lib>${java.home}/lib/rt.jar</lib>
                            </libs>
                            <dependencies>
                                <dependency>
                                    <groupId>net.sf.proguard</groupId>
                                    <artifactId>proguard-base</artifactId>
                                    <version>5.2</version>
                                    <scope>runtime</scope>
                                </dependency>
                            </dependencies>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <dependencies>
       <dependency>
            <groupId>org.spongepowered</groupId>
            <artifactId>spongeapi</artifactId>
            <version>3.0.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.easytesting</groupId>
            <artifactId>fest-assert-core</artifactId>
            <version>2.0M8</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>1.10.19</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.restlet.jse</groupId>
            <artifactId>org.restlet</artifactId>
            <version>${restlet-version}</version>
        </dependency>
        <dependency>
            <groupId>org.restlet.jse</groupId>
            <artifactId>org.restlet.ext.jackson</artifactId>
            <version>${restlet-version}</version>
        </dependency>
        <dependency>
            <groupId>com.googlecode.json-simple</groupId>
            <artifactId>json-simple</artifactId>
            <version>1.1.1</version>
        </dependency>
    </dependencies>
</project>
like image 106
Tunaki Avatar answered Sep 28 '22 04:09

Tunaki