ProGuard打破了JavaFX应用程序

时间:2015-03-27 18:00:12

标签: java javafx proguard classnotfoundexception fxml

我正在尝试模糊我的JavaFX应用程序,但它失败了。生成的结果不起作用,我不明白为什么。生成的jar只是失败,因为fxml文件不能再加载所有导入(ClassNotFoundException)。

部署工作流程:

  1. 构建可运行的jar(在IntelliJ knwon中作为工件)
  2. 使用ProGuard
  3. 混淆该jar
  4. 修复ProGuard无法执行的jar中的一些问题
  5. 1)最小示例应用

    示例应用程序'GuardTest'是一个由3个类组成的IntelliJ项目。

    • sample.Main:包含应用程序入口点并加载GUI fxml文件'sample.fxml'
    • sample.Controller:'sample.fxml'
    • 的控制器类
    • controls.CustomControl:一个从HBox继承的简单javafx控件。这在'sample.fxml'
    • 中使用

    'sample.fxml'的内容:

    <?import javafx.scene.control.Button?>
    <?import javafx.scene.layout.VBox?>
    
    <?import controls.CustomControl?>
    
    <VBox fx:controller="sample.Controller"
              xmlns:fx="http://javafx.com/fxml">
        <children>
            <CustomControl>
                <children>
                    <Button text="Test"></Button>
                </children>
            </CustomControl>
        </children>
    </VBox>
    

    2)混淆

    现在我使用ProGuard生成从上面项目生成的jar文件。我使用以下设置:

    -target 8
    
    -injars ./out/artifacts/JavaFXApp/JavaFXApp.jar
    
    -outjars ./out/obfuscated/Obfuscated.jar
    -ignorewarnings
    
    -printmapping ./out/obfuscated/proguard.map
    -dontusemixedcaseclassnames
    -dontshrink
    -dontoptimize
    -dontskipnonpubliclibraryclasses
    -dontskipnonpubliclibraryclassmembers
    
    #-flattenpackagehierarchy
    -repackageclasses 'p'
    -allowaccessmodification
    
    -libraryjars "<java.home>/lib/rt.jar"
    -libraryjars "<java.home>/lib/javaws.jar"
    -libraryjars "<java.home>/lib/ext/jfxrt.jar"
    
    -adaptresourcefilecontents **.fxml,**.properties,META-INF/MANIFEST.MF,images/*.jar,publicCerts.store,production.version
    
    -keepattributes javafx.fxml.FXML,Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod
    -keepclassmembers class * {
        @javafx.fxml.FXML *;
    }
    
    -keepclassmembernames public class com.javafx.main.Main, com.nywelt.sharkload.application.Main {
        public static void main(java.lang.String[]);
    }
    -keepclasseswithmembers public class com.javafx.main.Main, com.product.main.EntryFX, net.license.LicenseEntryPoint {
        public *; public static *;
    }
    

    3)修复一些(明显的)ProGuard故障

    生成的jar文件'Obfuscated.jar'具有以下结构:

    **Obfuscated.jar**
    - META-INF
    --> MANIFEST.MF
    - p
    --> a.class
    --> b.class
    --> c.class
    - sample
    --> sample.fxml
    

    主类通过使用以下行加载'sample.fxml'文件来启动GUI:

    Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
    

    因此,我必须将'sample.fxml'文件移动到文件夹p,以使上面的行再次起作用。我还修复了fxml文件中的一些问题,其中ProGuard忘记更改(现在混淆的)类名。

    现在结构如下:

    **Obfuscated_fixed.jar**
    - META-INF
    --> MANIFEST.MF
    - p
    --> a.class
    --> b.class
    --> c.class
    --> sample.fxml
    

    sample.fxml文件现在看起来像这样:

    <?import javafx.scene.control.Button?>
    <?import javafx.scene.layout.VBox?>
    
    <?import p.a?>
    
    <VBox fx:controller="p.b"
              xmlns:fx="http://javafx.com/fxml">
        <children>
            <a>
                <children>
                    <Button text="Test"></Button>
                </children>
            </a>
        </children>
    </VBox>
    

    问题

    现在这个罐子应该再次起作用,因为一切都好了。但它没有! fxml加载器无法加载CustomControl(现在命名/混淆'a.class')。那是为什么?

    启动jar文件时出现以下错误输出(我正在运行java版本1.8.0_40):

    E:\Eigene Programme\GuardTest\out\obfuscated>java -jar Obfuscated_fixed.jar
    Exception in Application start method
    Exception in thread "main" java.lang.reflect.InvocationTargetException
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
            at java.lang.reflect.Method.invoke(Unknown Source)
            at sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)
    Caused by: java.lang.RuntimeException: Exception in Application start method
            at com.sun.javafx.application.LauncherImpl.launchApplication1(Unknown So
    urce)
            at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$152(
    Unknown Source)
            at com.sun.javafx.application.LauncherImpl$$Lambda$49/849460928.run(Unkn
    own Source)
            at java.lang.Thread.run(Unknown Source)
    Caused by: javafx.fxml.LoadException:
    file:/E:/Eigene%20Programme/GuardTest/out/obfuscated/Obfuscated_fixed.jar!/p/sam
    ple.fxml
    
            at javafx.fxml.FXMLLoader.constructLoadException(Unknown Source)
            at javafx.fxml.FXMLLoader.importClass(Unknown Source)
            at javafx.fxml.FXMLLoader.processImport(Unknown Source)
            at javafx.fxml.FXMLLoader.processProcessingInstruction(Unknown Source)
            at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
            at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
            at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
            at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
            at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
            at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
            at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
            at javafx.fxml.FXMLLoader.load(Unknown Source)
            at p.c.start(Main.java:13)
            at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$159
    (Unknown Source)
            at com.sun.javafx.application.LauncherImpl$$Lambda$52/663980963.run(Unkn
    own Source)
            at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$172(Unknown
     Source)
            at com.sun.javafx.application.PlatformImpl$$Lambda$46/410424423.run(Unkn
    own Source)
            at com.sun.javafx.application.PlatformImpl.lambda$null$170(Unknown Sourc
    e)
            at com.sun.javafx.application.PlatformImpl$$Lambda$48/1149216748.run(Unk
    nown Source)
            at java.security.AccessController.doPrivileged(Native Method)
            at com.sun.javafx.application.PlatformImpl.lambda$runLater$171(Unknown S
    ource)
            at com.sun.javafx.application.PlatformImpl$$Lambda$47/1963387170.run(Unk
    nown Source)
            at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
            at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
            at com.sun.glass.ui.win.WinApplication.lambda$null$145(Unknown Source)
            at com.sun.glass.ui.win.WinApplication$$Lambda$36/237061348.run(Unknown
    Source)
            ... 1 more
    Caused by: java.lang.ClassNotFoundException
            at javafx.fxml.FXMLLoader.loadType(Unknown Source)
            ... 26 more
    
    E:\Eigene Programme\GuardTest\out\obfuscated>Pause
    Drücken Sie eine beliebige Taste . . .
    

    使用

    在主类中设置默认类加载器
    FXMLLoader.setDefaultClassLoader(this.getClass().getClassLoader());
    

    也无济于事。

    项目档案

    在这里您可以找到示例项目(IntelliJ): https://www.dropbox.com/s/ot51spvwk6lzo4k/GuardTest.zip?dl=0

    IntelliJ生成的jar工件被编译为: ./出/伪影/ JavaFXApp / JavaFXApp.jar

    混淆的Jar在以下位置找到: ./出/混淆/ Obfuscated.jar

    如上所述,混淆但固定(至少应该是)jar: ./出/混淆/ Obfuscated_fixed.jar

    要显示'sample.fxml'文件中的import语句导致问题我从fxml文件中删除了我的自定义控件并将其保存到(工作)jar: ./出/混淆/ Obfuscated_fixed_work.jar

    对不起,我很抱歉。我希望无论如何你会帮助我:)。

2 个答案:

答案 0 :(得分:9)

我找到了解决方案!问题是FXML无法导入不以大写字母开头的类。因此,必须提供ProGuard用于混淆的可用名称的自己的列表。这可以通过以下方式完成:

-classobfuscationdictionary obfuscationClassNames.txt

使用obfuscationClassNames.txt包含可用类名的行分隔列表:

A
B
C
D
...

答案 1 :(得分:0)

我使用了相同的步骤。我可以看到导入更新到fxml文件但不能使用它们。

获取例外:

  

javafx.fxml.LoadException:MenuBarControl不是有效类型。

但如果我看到fxml文件导入已更新但未使用。

< ? import q.A ? >
< ? import r.A ? >

 <VBox fx:id="top">
    <MenuBarControl fx:id="menuBarControl"/>
  </VBox>