简而言之:我无法使用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插件更让人困惑,因此,我放弃了这种方法
答案 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
现在我没有收到任何警告,一切都可以正常编译。