0

to make it short: I am unable to shrink my more complex scala programs with Proguard. I think I am overlooking something, but currently I have no Idea what it could be.

My Current setup relys upon a build.gradle-file to shrink my compiled fat-jar.

import proguard.gradle.ProGuardTask

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'net.sf.proguard:proguard-gradle:5.2.1'
    }
}

plugins {
    id 'application'
    id 'java'
    id 'scala'
}

mainClassName = 'app.Main'
sourceCompatibility = 1.8

repositories {
    ...
}

dependencies {
    ...
}


jar {
    manifest {
        attributes(
                'Class-Path': configurations.compileClasspath.files.collect {"$it.name"}.join(' '),
                'Main-Class': 'app.Main'
        )
    }
    from {
        configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) }
    }
}


task proguarding(type: ProGuardTask, dependsOn: jar) {
    configuration 'proguard-rules.pro'
    libraryjars files(configurations.compileClasspath.collect { it })
    injars "$buildDir/libs/Main.jar"
    outjars "$buildDir/libs/Shrunk.jar"
}

These are my proguard rules inside the proguard-rules.pro file

-keep class testing.** { *; }


-dontoptimize
-dontobfuscate
#-dontpreverify
#-dontnote

-ignorewarnings
-forceprocessing


-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

-dontwarn scala.**
-keep class !scala*.** { *; }

-dontwarn **$$anonfun$*
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers

-keep class ... # imagine like 5-thousend different keep-rules I tried

-keepclassmembers class * {
    ** MODULE$;
}

All the Programs/ Libs I tried to shrink so far didn't work after the shrinking.

Except for the most basic scala program:

package main

import java.io._

object Main extends App {
    val pw = new PrintWriter(new File("hello.txt" ))
    pw.write("Hello, world")
    pw.close()
}

This one I could shrink from 5.5mb to 432kb, but everything else won't work and instead throws me run time errors like NullPointerExceptions or something about the stackmap.

Exception in thread "main" java.lang.VerifyError: Expecting a stackmap frame at branch target 14
Exception Details:
  Location:
    generator/Main$.parameters()Lscalafx/application/JFXApp$Parameters; @4: ifne
  Reason:
    Expected stackmap frame at this location.
  Bytecode:
    0x0000000: 2ab4 0010 9a00 0a2a b700 1ca7 0007 2ab4
    0x0000010: 0011 b0                                

    at generator.Main.main(Main.scala)

I found out, that these problems arose through the dontpreverify-option, but If I don't use "-dontpreverify", it won't even compile.

Without that option ProGuard is not able to find superclasses (just like this guy)

So I tried every keep-option I could find. None of the solutions I found helped in any way. If anybody knows what's wrong, please help I am at the end of my nerves.

If somebody knows another shrinker for jar files that is actually easy to use, please tell me.

Btw, The GUI was even more confusing than the gradle plugin so, I ditched that approach

SleightX
  • 43
  • 1
  • 9
  • "instead throws me run time errors like NullPointerExceptions or something about the stackmap" — you basically always want to include exact and complete error texts, not paraphrases or summaries, when asking a programming question – Seth Tisue Sep 20 '18 at 19:44
  • I know, but I couldn't recreate these specific errors at the time of posting. Also, I already knew that it was because of the "-dontpreverify"-option. Hence the sentence after that statement. I will edit the post to make it clearer – SleightX Sep 21 '18 at 06:08

1 Answers1

1

The mistake I made, was not to include the java runtime jar from the jdk

Here is the gradle with the proguarding task

import proguard.gradle.ProGuardTask

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'net.sf.proguard:proguard-gradle:6.0.3'
    }
}

plugins { ... }

version '1.0'

mainClassName = 'app.Main'
sourceCompatibility = 1.8

repositories { ... }
dependencies { ... }


jar {
    manifest {
        attributes(
                'Class-Path': configurations.compileClasspath.files.collect {"$it.name"}.join(' '),
                'Main-Class': 'app.Main'
        )
    }
    from {
        configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

task proguarding(type: ProGuardTask, dependsOn: jar) {
    configuration 'proguard-rules.pro'
    libraryjars files(configurations.compileClasspath.collect { it })
    injars "$buildDir\\libs\\" + project.name + "-" +  version + ".jar"
    outjars "$buildDir\\libs\\" + project.name + "-" +  version + "_shrunk" + ".jar"
}

And here are the pro-guard rules inside proguard-rules.pro

-keep class app.** { *; }

#-dontoptimize
-dontobfuscate
#-dontnote
#-dontusemixedcaseclassnames
-ignorewarnings
-forceprocessing

-libraryjars  C:/Program Files/Java/jdk1.8.0_181/jre/lib/rt.jar
-libraryjars  C:/Program Files/Java/jdk1.8.0_181/jre/lib/ext/jfxrt.jar

Now I don't get any warnings and everything compiles just fine.

SleightX
  • 43
  • 1
  • 9