Обфускация JavaFX Proguard

Я борюсь с запутыванием приложения 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: -dontoptimize -dontshrink

-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?


person orzel    schedule 26.02.2019    source источник


Ответы (1)


Чтобы Proguard работал с Java 11, нам понадобятся:

  • Последняя бета-версия Proguard для Gradle в этом случае.

  • Измените файл сборки gradle, чтобы включить в него задачу proguard.

  • Добавьте файл конфигурации proguard, включая необходимые изменения для Java 11.

Build.gradle

Начиная с образца HelloFX, сборка будет быть изменен на:

// 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, я добавлю еще несколько задач, чтобы заменить стандартные сборки / классы на защищенные. Это помогает проверить результат.

// 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

Ключ к тому, как заставить его работать с Java 9+, можно найти в этом комментарии. Если вы загрузите исходный код и посмотрите папку с примерами, вы увидите, что есть разные файлы конфигурации.

Проверяя 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 успешно запустит приложение.

person José Pereda    schedule 26.02.2019
comment
Замечательно, спасибо, сработало (частично). Одна вещь, которая не сработала, - это (! **. Jar;! Module-info.class) - она ​​выдает исключение No such file. И с этим я получаю предупреждения Gradle, такие как: не могу найти ссылочный метод 'void setText (java.lang.String)' и не могу найти ссылочный метод 'javafx.scene.control.TableView getTableView ()', так что что-то не до библиотек. - person orzel; 27.02.2019
comment
Хорошо, поэтому я изменил конфигурацию задачи, так как мне нужен fatjar, и оказалось, что он заканчивается той же ошибкой (Duplicate jar entry [a.class]), поэтому я предполагаю, что сейчас проблема с зависимостями, а не с JavaFX и / или Java11 ... Любой иде, как это исправить? (Он отлично запутывает обычную банку) - person orzel; 27.02.2019
comment
Я только что взял образец hellofx и изменил его, как опубликовано. Вы можете попробовать это в первую очередь? Как только вы заставите его работать, начинайте вносить изменения. - person José Pereda; 27.02.2019
comment
Я только что изменил ввод proguard на генерируемый мною fatjar: injars $ {buildDir} /libs/out.jar, обычные jar запутываются. - person orzel; 27.02.2019
comment
Привет, Хосе, я все еще борюсь с этим, на самом деле несколько дней подряд, прихожу к выводу, что невозможно успешно запутать код JavaFX с помощью proguard. В настоящее время у меня проблема с файлами FXML. На самом деле я исключил файл FXML и соответствующий класс View из обфускации, они находятся в том же каталоге внутри jar, как и в не обфусцированном Jar, и выдает префикс Unexpected namespace: .. Не знаю, как продолжить с этим ... - person orzel; 01.03.2019
comment
Вы можете запутать код JavaFX с помощью Proguard, но не весь его. Части FXML более сложны, поскольку широко используются инжекция / отражение. Как отмечалось ранее, начните с основ, получите что-нибудь работающее и начните добавлять параметры в свой файл proguard.conf. Если хотите, создайте образец репозитория GitHub, и мы сможем там поработать ... - person José Pereda; 01.03.2019
comment
Это не сработает, если вы запустите Proguard из командной строки (proguard.sh @ proguard.conf). Есть ошибки: не удается найти класс, на который указывает ссылка .... Как бы вы это исправить, пожалуйста? - person Patrick; 25.10.2019
comment
@Patrick, пожалуйста, задайте новый вопрос со своими деталями, что вы сделали, а что не удалось. - person José Pereda; 25.10.2019
comment
Патрик, ты решил это? Я получаю ту же ошибку, не могу найти указанный класс - person SHASHA; 29.10.2019
comment
@Patrick Я думаю, что исправил, добавив: -dontwarn java. ** -keep class java. ** {; } -keep interface java. * {*;} - person SHASHA; 31.10.2019
comment
@ JoséPereda Мне пришлось добавить эти строки в proguard.conf. Не уверен, что это правильно. - person SHASHA; 31.10.2019