Facing an error with "Can't find common super class of " while obfuscating a maven based Java application

We are trying to obfuscate a jar which is basically a maven based Java application using Proguard (version 7.2.0-beta4)
Need help in troubleshooting the error we are facing.
I have provided pom.xml and proguard.conf in order to reproduce the issue. (Can have any sample hello world java project with below pom.xml)
I have tried configuring proguard within pom.xml (shared below) and have defined the proguard configs as below

----------------------------Start of proguard.conf ------------------------------
-keep public class io.engine.Main {
public static void main(java.lang.String[]);
}
-injars …/sample-1.0-SNAPSHOT-jar-with-dependencies.jar
-outjars indexer-obfuscated.jar
-dontwarn
-printmapping proguard.map

-dontnote

----------------------------End of proguard.conf ------------------------------

----------------------------- Start of pom.xml ----------------------------------

<?xml version="1.0" encoding="UTF-8"?>


4.0.0

<groupId>io.engine</groupId>
<artifactId>sample</artifactId>
<version>1.0-SNAPSHOT</version>

<dependencies>
    <dependency>
        <groupId>com.codahale.metrics</groupId>
        <artifactId>metrics-core</artifactId>
        <version>3.0.2</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-common</artifactId>
        <version>3.3.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.parquet</groupId>
        <artifactId>parquet-hadoop</artifactId>
        <version>1.11.1</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.31</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-aws</artifactId>
        <version>3.3.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-client</artifactId>
        <version>3.3.1</version>
    </dependency>
    <dependency>
        <groupId>org.mapdb</groupId>
        <artifactId>mapdb</artifactId>
        <version>3.0.8</version>
    </dependency>
    <dependency>
        <groupId>org.apache.calcite</groupId>
        <artifactId>calcite-babel</artifactId>
        <version>1.27.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.thrift</groupId>
        <artifactId>libthrift</artifactId>
        <version>0.15.0</version>
    </dependency>
</dependencies>
<properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
</properties>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>3.1.1</version>

            <configuration>
                <archive>
                    <manifest>
                        <mainClass>io.engine.Main</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>
        <plugin>
            <groupId>com.github.wvengen</groupId>
            <artifactId>proguard-maven-plugin</artifactId>
            <executions>
                <execution>
                    <id>obfuscation-packaging</id>
                    <phase>package</phase>
                    <goals>
                        <goal>proguard</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <!-- Our application is so big that ProGuard had ran out of memory -->
                <maxMemory>4096m</maxMemory>

                <!-- File with proguard configuration. Provide path -->
                <proguardInclude>./proguard.conf
                </proguardInclude>

                <!-- Now exclude all modules that are embedded in the jar, so that
                    ProGuard won't see a redefinition of each single class.-->
                <exclusions>
                    <exclusion>
                        <groupId>io.engine</groupId>
                        <artifactId>sample</artifactId>
                    </exclusion>

                </exclusions>

                <!--
                    List external jars your application depends on
                    (that not listed in maven dependencies).
                    You probably depend on Java runtime (rt.jar).
                -->
                <libs>
                    <lib>${java.home}/lib/rt.jar</lib>
                </libs>
            </configuration>
        </plugin>
    </plugins>
</build>

--------------------------------- End of pom.xml ---------------------------------------

Error encountered

[proguard] ProGuard, version 7.2.0-beta4
[proguard] Unexpected error while performing partial evaluation:
[proguard] Unexpected error while performing partial evaluation:
[proguard] Class = [org/apache/calcite/avatica/proto/Responses$ConnectionSyncResponse]
[proguard] Class = [org/apache/calcite/avatica/proto/Responses$DatabasePropertyElement]
[proguard] Method = [(Lcom/google/protobuf/CodedInputStream;Lcom/google/protobuf/ExtensionRegistryLite;)V]
[proguard] Exception = [proguard.evaluation.IncompleteClassHierarchyException] (Can’t find common super class of [org.apache.calcite.avatica.proto.Responses$RpcMetadata$Builder] (with 1 known super classes: org.apache.calcite.avatica.proto.Responses$RpcMetadata$Builder) and [org.apache.calcite.avatica.proto.Common$TypedValue$Builder] (with 1 known super classes: org.apache.calcite.avatica.proto.Common$TypedValue$Builder))
[proguard] Method = [(Lcom/google/protobuf/CodedInputStream;Lcom/google/protobuf/ExtensionRegistryLite;)V]
[proguard] Exception = [proguard.evaluation.IncompleteClassHierarchyException] (Can’t find common super class of [org.apache.calcite.avatica.proto.Responses$RpcMetadata$Builder] (with 1 known super classes: org.apache.calcite.avatica.proto.Responses$RpcMetadata$Builder) and [org.apache.calcite.avatica.proto.Common$ConnectionProperties$Builder] (with 1 known super classes: org.apache.calcite.avatica.proto.Common$ConnectionProperties$Builder))

Dear @Aaquib_Khan ,

Thank you for raising this question.

It looks like certain superclasses cannot be found.

The part of the output you shared contains some errors but most likely, above those errors, some warnings showed up which already indicated that some superclasses could not be found.

Please find an important part of the [troubleshooting manual page] below (ProGuard Manual: Troubleshooting | Guardsquare):

Error: Can’t find common super class of … and …

It seems like you tried to avoid the warnings from the previous paragraph by specifying -ignorewarnings or -dontwarn, but it didn’t work out. ProGuard’s optimization step and preverification step really need the missing classes to make sense of the code. Preferably, you would solve the problem by adding the missing library, as discussed. If you’re sure the class that references the missing class isn’t used either, you could also try filtering it out from the input, by adding a filter to the corresponding -injars option: “-injars myapplication.jar(!somepackage/SomeUnusedClass.class)”. As a final solution, you could switch off optimization (-dontoptimize) and preverification (-dontpreverify).

Please let us know if this information allows you to solve the issue.

Kind regards,

Ewout

1 Like

Thank you so much for the inputs. Actually the superclass which it was complaining about was from the library dependencies which was not used by our code directly. I tried switching off optimizations and preverification. It was then able to generate obfuscated jar but when i try to use that obfuscated jar, i get below errors

Exception in thread “main” java.lang.ExceptionInInitializerError
at com.amazonaws.thirdparty.jackson.databind.ObjectMapper.(Unknown Source)
at com.amazonaws.internal.config.InternalConfig.(Unknown Source)
at com.amazonaws.internal.config.InternalConfig$Factory.(Unknown Source)
at com.amazonaws.util.VersionInfoUtils.userAgent(Unknown Source)
at com.amazonaws.util.VersionInfoUtils.initializeUserAgent(Unknown Source)
at com.amazonaws.util.VersionInfoUtils.getUserAgent(Unknown Source)
at com.amazonaws.internal.EC2ResourceFetcher.(Unknown Source)
at com.amazonaws.auth.InstanceMetadataServiceCredentialsFetcher.(Unknown Source)
at com.amazonaws.auth.InstanceProfileCredentialsProvider.(Unknown Source)
at com.amazonaws.auth.InstanceProfileCredentialsProvider.(Unknown Source)
at com.amazonaws.auth.InstanceProfileCredentialsProvider.(Unknown Source)
at com.amazonaws.auth.InstanceProfileCredentialsProvider.(Unknown Source)
at com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper.initializeProvider(Unknown Source)
at com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper.(Unknown Source)
at com.amazonaws.auth.DefaultAWSCredentialsProviderChain.(Unknown Source)
at com.amazonaws.auth.DefaultAWSCredentialsProviderChain.(Unknown Source)
at com.amazonaws.services.s3.AmazonS3ClientBuilder.standard(Unknown Source)
at io.e6x.b.s.a(Unknown Source)
at io.e6x.b.s.b(Unknown Source)
at io.e6x.b.a.c.f(Unknown Source)
at io.e6x.c.a.a.a.getTableMap(Unknown Source)
at io.e6x.c.a.a.a.(Unknown Source)
at io.e6x.a.b(Unknown Source)
at io.e6x.Main.main(Unknown Source)
Caused by: java.lang.NullPointerException
at com.amazonaws.thirdparty.jackson.databind.introspect.VisibilityChecker$Std.(Unknown Source)
at com.amazonaws.thirdparty.jackson.databind.introspect.VisibilityChecker$Std.(Unknown Source)
… 24 more

I have tried including all the library classes in proguard.conf

---------------------------------- Start of proguard.conf -----------------------------------
-keep public class io.e6x.Main {
public static void main(java.lang.String[]);
}
-keep class javax.** { ; }
-keep class org.
* { ; }
-keep class java.
* { ; }
-keep class com.
* { ; }
-keep class sun.
* { ; }
-keep class io.netty.
* {*; }
-injars /Users/aaquibkhan/Documents/Work/e6x-indexer/target/e6x-indexer-1.0-SNAPSHOT-jar-with-dependencies.jar
-outjars indexer-obfuscated.jar
-dontwarn
-printmapping proguard.map
-dontoptimize
-dontpreverify
-dontnote
------------------------------------- End of proguard.conf

Dear @ewoutd,
I was able to resolve the issues which were happening internally from the jar. For now, I think there is no issue with proguard.
But would like to understand the downsides of switching off the warnings, the optimization and the preverification. Do they have any impact on the final security of the jar ?

Dear @Aaquib_Khan ,

Good to hear that you were able to resolve the issues.

  • Suppressing all warnings is something you can do if you are sure they do not contain any useful information that might help you debug certain (runtime) issues. This will not impact the security of the jar.

  • The optimizer step optimizes bytecode and removes unused instructions. Disabling this will thus not impact the security of the jar.

  • The final preverification step adds preverification information to the classes, which is required for Java Micro Edition and for Java 6 and higher. Disabling this will thus not impact the security of the jar.

Kind regards,

Ewout

Dear @ewoutd ,
Thanks a lot for all the clarifications

1 Like