使用ProGuard缩小Scala

时间:2018-09-20 15:59:24

标签: scala gradle proguard

简而言之:我无法使用Proguard缩减更复杂的Scala程序。我认为我正在忽略某些东西,但是目前我不知道它可能是什么。

我当前的设置依赖于build.gradle文件来缩小编译的胖子。

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"
}

这些是我在proguard-rules.pro文件中的proguard规则

-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$;
}

到目前为止,我尝试缩小的所有程序/库在缩小之后都无法正常工作。

最基本的scala程序除外:

package main

import java.io._

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

我可以将它的大小从5.5mb缩小到432kb,但是其他所有内容都将无法工作,而会抛出诸如NullPointerExceptions之类的运行时错误或有关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)

我发现,这些问题是通过dontpreverify-option引起的,但是如果我不使用“ -dontpreverify”,它甚至不会编译。

没有该选项,ProGuard将无法找到超类(就像this guy一样)

因此,我尝试了所有可以找到的保持选项。 我发现的解决方案都没有任何帮助。如果有人知道出了什么问题,请帮助我,尽我所能。

如果有人知道另一个易于使用的jar文件收缩器,请告诉我。

顺便说一句,GUI比gradle插件更让人困惑,因此,我放弃了这种方法

1 个答案:

答案 0 :(得分:0)

我犯的错误是没有包括jdk中的Java运行时jar

这是执行保护任务的重点

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"
}

这是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

现在我没有收到任何警告,一切都可以正常编译。