New to proguard, cant get it to do very simple shrinking

I have a relatively big monorepo, this is where i experiment with things and have all my own libraries and utilities and use latest jdk and language versions.

Very recently i wanted to write a simple application and i do not want to copy utils from this repo on demand into fresh blank repository (which is what i did in the past when i needed something like this). Instead what i want to do is write my application in the repo, then let proguard figure out all the stuff i do not use and give me an efficient jar.

So to not overcomplicate my life with gradle or maven i just use standalone version (7.5.0) pointed it to a very simple config file which looks like this

-injars       target/alp-1.0-SNAPSHOT.jar # this is uber jar 48MB thick
-outjars      target/alp.jar # the result is 8.7MB
-libraryjars  <java.home>/jmods/java.base.jmod(!**.jar;!module-info.class)

-ignorewarnings
-dontwarn
-verbose

-keep public class alp.MainKt {
    public static void main(java.lang.String[]);
}

The class in question is very trivial

package alp

fun main() {
    println("hello")
}

naturally i want to test if its smart enough to literally eliminiate everything except this class, since it will work with this single class file in the entire jar.

After proguard is done i get the jar, extract its contents and i have all the garbage in the world.

The result jar runs and prints the message, you can see that MainKt is there but all this other stuff…

I do not really care about obfuscation and any optimizations at all, this is a desktop application that only me will likely use. What puzzles me is that there was not a single example in the docs or out there in stack overflow that would achieve this simple goal.

I do not know why proguard doesn’t ignore all this garbage, frankly it should have started with the only keep option i gave it, then realize there are literally no imports and be done right there and if i have something else to be dragged along then i should add more rules.

Any help is appreciated.

here is some of the logs in case it may be helpful (ignoring a lot of nonsensical warnings that cant find classes that are literally in the uber jar).

Note: you're ignoring all warnings!
Ignoring unused library classes...
  Original number of library classes:              7491
  Final number of library classes:                 959
Marking classes and class members to be kept...
Inlining subroutines...
Shrinking...
Removing unused program classes and class elements...
  Original number of program classes:            24615
  Final number of program classes:               387
Optimizing (pass 1/1)...
  Number of finalized classes:                   117
  Number of unboxed enum classes:                1
  Number of vertically merged classes:           0   (disabled)
  Number of horizontally merged classes:         0   (disabled)
  Number of merged wrapper classes:              0   (disabled)
  Number of removed write-only fields:           269
  Number of privatized fields:                   241
  Number of generalized field accesses:          86
  Number of specialized field types:             35
  Number of inlined constant fields:             38
  Number of privatized methods:                  213
  Number of staticized methods:                  46
  Number of finalized methods:                   780
  Number of desynchronized methods:              0
  Number of simplified method signatures:        37
  Number of removed method parameters:           15
  Number of generalized method invocations:      202
  Number of specialized method parameter types:  24
  Number of specialized method return types:     119
  Number of inlined constant parameters:         83
  Number of inlined constant return values:      7
  Number of inlined short method calls:          249
  Number of inlined unique method calls:         246
  Number of inlined tail recursion calls:        3
  Number of merged code blocks:                  6
  Number of variable peephole optimizations:     1192
  Number of arithmetic peephole optimizations:   44
  Number of cast peephole optimizations:         62
  Number of field peephole optimizations:        20
  Number of branch peephole optimizations:       461
  Number of object peephole optimizations:       16
  Number of string peephole optimizations:       279
  Number of math peephole optimizations:         0
  Number of simplified instructions:             156
  Number of removed instructions:                1194
  Number of removed local variables:             51
  Number of removed exception blocks:            53
  Number of optimized local variable frames:     432
Shrinking...
Removing unused program classes and class elements...
  Original number of program classes:            387
  Final number of program classes:               370
Obfuscating...
  Number of obfuscated classes:                  369
  Number of obfuscated fields:                   727
  Number of obfuscated methods:                  1406
Preverifying...
Writing output...

Take a look at:

as a reference.

You need to include the rules of the supported libraries, if a library use dynamic class loading, and reflections, you need to keep it manually with rules, it seems that you use OkHttp and Google Guava, both require including some rules:

okhttp/features/r8_proguard/
google/guava/wiki/UsingProGuardWithGuava

I’m not sure about other usages or libraries, you will have to either keep them completely (disable shrinking for specific packages instead of specific functions or classes) or solve it with rules.

Also, you have included the java.base module, if you require other Java modules, either include them all in -libraryjars or include what you need instead.

Note: I’m able to only include two links for this post.

1 Like

The problem is i don’t want to include more stuff, i’m literally pointing to a main that does hello world to test it, and it still pulls a lot of stuff that i didn’t expect it to bring.

If anything i expected it to bring less stuff then me manually adding classes/dependencies until everything is good. Ideally proguard would literally just include that one class.

So im not sure if i’m doing something wrong or this is good enough for most people that use proguard? cos it did reduce 48MB to 8Mb but what it could do was few Kb…

It kept everything in resources folder, it kept a whole host of classes that have not been used or included in any imports…

It is possible that ProGuard is not recognizing those classes as needing shrinking. ProGuard is only going to remove classes as well, rather than removing any of the additional files. I would also recommend using the -whyareyoukeeping command to determine what is causing specific classes to not be shrank. You can find the documentation for that command here: ProGuard Manual: Usage | Guardsquare

2 Likes

Awesome that command is what i needed.

1 Like