I was trying to learn how to use ProGuard, and it is no way as easy as I thought. At first I found a simple Java code to try it, a simple two class Swing calculator.
Here is solution with gradle
Create a runnable jar with all dependent libraries copied to a directory "dependencies" and add the classpath in the manifest.
task createJar(type: Jar) {
println("Cleaning...")
clean
manifest {
attributes('Main-Class': 'com.abc.gradle.hello.App',
'Class-Path': configurations.default.collect { 'dependencies/' +
it.getName() }.join(' ')
)
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it)
}
} with jar
println "${outputJar} created"
}
Copy the dependencies
task copyDepends(type: Copy) {
from configurations.default
into "${dependsDir}"
}
Obfuscate the library with Proguard
task proguard(type: proguard.gradle.ProGuardTask) {
println("Performing obfuscation..")
configuration 'proguard.conf'
injars "${outputJar}"
outjars "${buildDir}/libs/${rootProject.name}_proguard.jar"
libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
libraryjars "${dependsDir}"
}
Here is the complete build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'net.sf.proguard:proguard-gradle:6.0.3'
classpath 'net.sf.proguard:proguard-base:6.0.3'
}
}
plugins {
id 'java'
id 'application'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.slf4j:slf4j-api:1.7.30'
implementation 'ch.qos.logback:logback-classic:1.2.3'
implementation 'ch.qos.logback:logback-core:1.2.3'
testImplementation 'junit:junit:4.13'
}
def outputJar = "${buildDir}/libs/${rootProject.name}.jar"
def dependsDir = "${buildDir}/libs/dependencies/"
def runnableJar = "${rootProject.name}_fat.jar";
task copyDepends(type: Copy) {
from configurations.default
into "${dependsDir}"
}
task createJar(type: Jar) {
println("Cleaning...")
clean
manifest {
attributes('Main-Class': 'com.abc.gradle.hello.App',
'Class-Path': configurations.default.collect { 'dependencies/' +
it.getName() }.join(' ')
)
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
} with jar
println "${outputJar} created"
}
task proguard(type: proguard.gradle.ProGuardTask) {
println("Performing obfuscation..")
configuration 'proguard.conf'
injars "${outputJar}"
outjars "${buildDir}/libs/${rootProject.name}_proguard.jar"
libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
libraryjars "${dependsDir}"
}
Proguard.conf
-keep public class * {
public * ;
}
Gradle commands to obfuscate
gradle createJar
gradle copyDepends
gradle proguard
I've had similar problems, solved by taking out Java modifiers.
Java modifiers such as visibility modifiers are optional in the ProGuard configuration file -keep option (and in related options -keepclassmembers etc.)
From manual: -keep [,modifier,...] class_specification
So unless there is a specific reason otherwise, you can leave them out.
I got it to work using the following configuration file:
-injars calc.jar
-outjars calc_obf.jar
-libraryjars <java.home>/lib/rt.jar
-keep class Calc {
public static void main(java.lang.String[]);
}
Most notably, I ditched the public
in front of class Calc
.