Incremental obfuscation not working

Hi, I have a two custom libraries lib1 and lib2, which are added into my project as a dependency.

My requirement is to obfuscate my project along with lib1 and lib2.

What I tried is I obfuscated lib1 and lib2 and saved it’s -printMapping into a file.

While obfuscating the project I am applying this mapping, but when I run the jar I keep getting errors for obfuscated classes “Error creating Bean : Lookup method resolution failed.”

When I unzipped my project’s obfuscated jar, BOOT-INF/lib had unobfuscated jars of lib1 and lib2.

How can I obfuscate my libraries (added as dependencies) while obfuscating main project.

My project is built using spring boot (3.2.2) and proguard (7.4.2) for obfuscation.

Please check below gradle proguardTask and rules.pro file.

proguardTask
task proguard(type: ProGuardTask) {
dependsOn tasks.extractJar

verbose

injars "${buildDir}/extracted/BOOT-INF/classes"
outjars "${buildDir}/obfuscatedClasses.jar"

configuration proguardConfig

// Automatically handle the Java version of this build.
if (System.getProperty('java.version').startsWith('1.')) {
    // Before Java 9, the runtime classes were packaged in a single jar file.
    libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
} else {
    // As of Java 9, the runtime classes are packaged in modular jmod files.
    libraryjars "${System.getProperty('java.home')}/jmods/java.base.jmod", jarfilter: '!**.jar', filter: '!module-info.class'
    //libraryjars "${System.getProperty('java.home')}/jmods/....."
}

// This will contain the Spring dependencies.
libraryjars sourceSets.main.compileClasspath

// Keep the main class entry point.
keep 'public class com.example.Application { \
        public static void main(java.lang.String[]); \
     }'

keep 'public class org.springframework.boot.loader.JarLauncher'

keepattributes '*Annotation*'

// This simple example requires classes with @Component annotation classes
// to be kept, since otherwise components could end up with clashing names,
// if they do not set the name explicitly.
keep 'public @org.springframework.stereotype.Component class *'
keep 'public @org.springframework.context.annotation.Configuration class *'
keep 'public @org.springframework.boot.context.properties.ConfigurationProperties class *'
keep 'public @org.springframework.boot.autoconfigure.SpringBootApplication class *'
keep 'public @org.springframework.stereotype.Service class *'
keep 'public @org.springframework.ws.server.endpoint.annotation.Endpoint class *'

// You may need to keep classes or members based on other annotations such as:
keepclassmembers 'public class * { \
        @org.springframework.beans.factory.annotation.Autowired *; \
        @org.springframework.beans.factory.annotation.Value *; \
        @org.springframework.beans.factory.annotation.Qualifier *; \
        @org.springframework.beans.factory.annotation.Required *; \
        @org.springframework.context.annotation.Bean *; \
        @org.springframework.context.annotation.Primary *; \
        @org.springframework.boot.context.properties.ConfigurationProperties *; \
        @org.springframework.boot.context.properties.EnableConfigurationProperties *; \
        @javax.inject.Inject *; \
        @javax.annotation.PostConstruct *; \
        @javax.annotation.PreDestroy *; \
    }'

// After ProGuard has executed, repackage the app.
finalizedBy tasks.repackage

}

rules.pro
-keep class javax.xml.** { ; }
-keepclassmembernames class * {
java.lang.Class class$(java.lang.String);
java.lang.Class class$(java.lang.String, boolean);
}
-dontoptimize
-dontshrink
-adaptclassstrings
-keepattributes Exceptions, InnerClasses, Signature, Deprecated, SourceFile, LineNumberTable, Annotation, EnclosingMethod, RuntimeVisibleTypeAnnotations, RuntimeInvisibleTypeAnnotations
-keepnames interface **
-keepparameternames
-keep interface * extends * { ; }
-keep class com.fasterxml.jackson.
{ ; }
-dontwarn javax.xml.
*
-keepdirectories com.example.**
-applymapping proguard.map
-keepattributes SourceFile, LineNumberTable
-keepattributes LocalVariableTable, LocalVariableTypeTable
-addconfigurationdebugging
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers

Hi there,

To clarify, are you first obfuscating lib1 and lib2, and then adding the obfuscated libraries into your project and obfuscating that project? And you are using printMapping to keep the obfuscation mapping the same?

We typically recommend doing one obfuscation pass (i.e. obfuscating the libraries after it has been consumed) as that streamlines the process.

If you would like to continue with your use case, I would suggest using consumer rules instead. Please check this manual page for more information.

Lastly, when there are elements of your project that remain unobfuscated, that typically means that there is a keep rule out there preventing its obfuscation. I would recommend using the Proguard Library to quickly check your keep rules.

Hope this helps!

Cheers,
Amy

1 Like

Hi Amy,

Thanks for the reply!

No, I am separately obfuscating lib1 & lib2 and applying its mapping the current project, so dependencies are firstly added in build.gradle and then project is obfuscated altogether.

So my requirement is when I will run obfuscation on project it should obfuscate lib1 and lib2 along with it, I am applying mapping to change imports of classes from those 2 libraries in current project to avoid conflicts.

But when I unzip the jar and check lib folder, the content of lib1 and lib2 are unobfuscated there.

Can you let me know how to obfuscate the jars from the dependencies.

If I use the consumer rules, how can my application pick up the consumer rules of lib1 and lib2 during obfuscation?

Also in the documentation consumer rules are found in Android Gradle setup, but I am using Spring Boot with Gradle.

Best Regards,
Jyoti

Hi @Amy_Chien
Could you please update on above query.

Hi Jyoti,

My apologies for the late reply.

Typically, if there are unobfuscated libraries, that means that there is a keep rule preventing its obfuscation. I would thus recommend using the Proguard Playground to check your keep rules. Since it was not obfuscated at all, this likely means that your first obfuscation step was not successful - hence, I would recommend looking at the full configuration file of your first step (i.e. when you first obfuscate libraries 1 and 2).

As you can see, this process can become complicated, as each step has its own configuration file. We thus recommend only obfuscating everything together as the very last step, so you can simplify the workflow (and thus the debugging) of these issues.

Kind regards,
Amy

1 Like

@Amy_Chien
Could you please clear my below doubts.

  1. Is multi module obfuscation possible through proguard for project build using springBoot.
  2. If yes, how to obfuscate below example project.
  • Project A is build using spring boot.
  • It has module 1, module 2 and module 3.
  • module 1 uses module 2 and module 3 as implementation project, so those are getting added as library in module 1 jars’s BOOT-INF/lib folder.
  • when I run proguard task given in first query for module 1, how to obfuscate module 2 and module 3 along with it.

**with the current rules mentioned above, module 2 and module 3 does not get obfuscated.

I want to know how to obfuscate dependency jars while running obfuscation on main project.