【问题标题】:JavaFX Proguard ObfuscationJavaFX Proguard 混淆
【发布时间】:2019-07-20 09:41:18
【问题描述】:

我正在为 JavaFX 应用程序的混淆而苦苦挣扎。以此项目为基础:

https://github.com/openjfx/samples/tree/master/IDE/IntelliJ/Non-Modular/Gradle

Proguard 抛出此错误:

java.io.IOException: Can't write [Path\infile.jar] (Can't read [Path\outfile.jar] (Duplicate jar entry [a.class]))

Proguard 配置文件: -不要优化 -不要收缩

-libraryjars 'E:\Prog\jdk-11.0.2\jmods'
-libraryjars 'E:\Prog\javafx-sdk\lib'

# Save meta-data for stack traces
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable

# Rename FXML files together with related views
-adaptresourcefilenames **.fxml,**.png,**.css
-adaptresourcefilecontents **.fxml
-adaptclassstrings

# Keep all annotations and meta-data
-keepattributes *Annotation*,Signature,EnclosingMethod

# Keep entry-point class
-keep classpackage.App {
    public static void main(java.lang.String[]);
}

# Keep all classes inside application
-keep,allowobfuscation class package.** {
}

# Keep names of fields marked with @FXML attribute
-keepclassmembers class * {
    @javafx.fxml.FXML *;
}

有人有 JavaFX 混淆的经验吗?

【问题讨论】:

    标签: javafx proguard obfuscation java-11 javafx-11


    【解决方案1】:

    要让 Proguard 使用 Java 11,我们需要:

    • 最新的 Proguard beta version,在这种情况下用于 Gradle。

    • 修改构建 gradle 文件以包含 proguard 任务。

    • 添加一个 proguard 配置文件,包括 Java 11 所需的更改。

    Build.gradle

    从HelloFXsample开始,构建会修改为:

    // 1. Include proguard dependency
    buildscript {
        repositories {
            jcenter()
        }
        dependencies {
            classpath 'net.sf.proguard:proguard-gradle:6.1.0beta2'
        }
    }
    
    plugins {
      id 'application'
      id 'org.openjfx.javafxplugin' version '0.0.7'
    }
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
    }
    
    javafx {
        modules = [ 'javafx.controls', 'javafx.fxml' ]
    }
    
    mainClassName = 'org.openjfx.MainApp'
    

    我将添加更多任务,而不是仅仅添加 proguard 任务,以用 proguarded 替换默认构建/类。这有助于检查结果。

    // 2. Add tasks
    
    // 2.1 Clean buildDir before running proguard
    task cleanClasses(type: Delete) {
        delete "${buildDir}/classes/java/main"
        delete "${buildDir}/resources/java/main"
    }
    
    classes.dependsOn(cleanClasses)
    
    // 2.2 Add proguard task
    task proguard(type: proguard.gradle.ProGuardTask, dependsOn: classes) {
        injars project.sourceSets.main.output
        outjars "${buildDir}/proguard/output.jar"
    
        libraryjars project.sourceSets.main.compileClasspath
    
        configuration 'proguard.conf'
    }
    
    // 2.3 Clean after proguard task
    task cleanAfterProguard(type: Delete, dependsOn: proguard) {
        delete "${buildDir}/classes/java/main"
        delete "${buildDir}/resources/java/main"
    }
    
    // 2.4 Extract output jar to buildDir 
    task unpackProguardOutput (type: Copy, dependsOn: cleanAfterProguard) {
        from zipTree("${buildDir}/proguard/output.jar")
        into file("${buildDir}/classes/java/main")
    }
    

    最后,添加一个任务来运行带有保护类的应用程序。

    // 3. Create a task to run the app with the proguarded buildDir
    task runProguard(type: JavaExec, dependsOn: unpackProguardOutput) {
        classpath = sourceSets.main.runtimeClasspath
        jvmArgs = ['--module-path', classpath.asPath,
                   '--add-modules', 'javafx.controls,javafx.fxml' ]
        main = 'a.a.b' // <-- this name will depend on the proguard result
    }
    

    proguard.conf

    comment 中可以找到如何让它与 Java 9+ 一起工作的关键。如果你下载源代码,并查看examples文件夹,有不同的配置文件。

    查看applications.pro,可以阅读:

    # Before Java 9, the runtime classes were packaged in a single jar file.
    #-libraryjars <java.home>/lib/rt.jar
    
    # As of Java 9, the runtime classes are packaged in modular jmod files.
    -libraryjars <java.home>/jmods/java.base.jmod(!**.jar;!module-info.class)
    

    就是这样!

    这是我在 HelloFX 示例中使用的配置文件(当然它可以使用其他许多选项进行扩展):

    -dontoptimize
    -dontshrink
    
    #Java 9+
    -libraryjars <java.home>/jmods/java.base.jmod(!**.jar;!module-info.class)
    
    # Save meta-data for stack traces
    -printmapping out.map
    -renamesourcefileattribute SourceFile
    -keepattributes SourceFile,LineNumberTable
    
    # Rename FXML files together with related views
    -adaptresourcefilenames **.fxml,**.png,**.css,**.properties
    -adaptresourcefilecontents **.fxml
    -adaptclassstrings
    
    # Keep all annotations and meta-data
    -keepattributes *Annotation*,Signature,EnclosingMethod
    
    # Keep entry-point class
    -keep class org.openfjx.MainApp {
      public static void main(java.lang.String[]);
    }
    
    # Keep names of fields marked with @FXML, @Inject and @PostConstruct attributes
    -keepclassmembers class * {
      @javafx.fxml.FXML *;
      @javax.inject.Inject *;
      @javax.annotation.PostConstruct *;
    }
    

    结果

    如果你运行./gradlew proguard,你会得到output.jar

    如果你运行./gradlew unpackProguardOutput,你可以在build/classes看到结果:

    main
    |____a
    | |____a
    | | |____styles.css
    | | |____scene.fxml
    | | |____b.class
    | | |____a.class
    

    在这种情况下,b.class 是主类,所以这就是我在runProguard 任务中设置main = 'a.a.b' 的原因。显然,这取决于每种情况。

    另外,您可以查看 out.map:

    org.openjfx.FXMLController -> a.a.a:
        javafx.scene.control.Label label -> label
        10:10:void <init>() -> <init>
        17:20:void initialize(java.net.URL,java.util.ResourceBundle) -> initialize
    org.openjfx.MainApp -> a.a.b:
        11:11:void <init>() -> <init>
        15:23:void start(javafx.stage.Stage) -> start
        26:27:void main(java.lang.String[]) -> a
    

    最后,./gradlew runProguard 将成功运行应用程序。

    【讨论】:

    • 太棒了,谢谢,它起作用了(部分)。不起作用的一件事是 (!**.jar;!module-info.class) - 它抛出 No such file 异常。并且我收到了gradle警告,例如:找不到引用的方法'void setText(java.lang.String)'并且找不到引用的方法'javafx.scene.control.TableView getTableView()'等等没有库。
    • 好的,所以我修改了任务配置,因为我需要一个 fatjar,结果它以相同的错误结束(重复的 jar 条目 [a.class]),所以我认为这是依赖项的问题现在,不使用 JavaFX 和/或 Java11 ......知道如何解决这个问题吗? (它可以很好地混淆常规 jar)
    • 我刚刚获取了 hellofx 示例,并按照发布的内容对其进行了修改。你能先试试吗?一旦你让它工作,开始做修改。
    • 我刚刚将 proguard 的输入修改为我生成的 fatjar:injars "${buildDir}/libs/out.jar",普通 jar 混淆就好了。
    • 如果在命令行运行 Proguard (proguard.sh @proguard.conf) 将不起作用。有错误“找不到引用的类...”。请问如何解决这个问题?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-21
    • 1970-01-01
    相关资源
    最近更新 更多