ProGuard打破了JavaFX应用程序

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

部署工作流程:

  1. 构建可运行的jar(在IntelliJ knwon中作为工件)
  2. 使用ProGuard混淆该jar
  3. 修复ProGuard无法完成的jar中的一些问题

1)最小的示例应用程序

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

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

‘sample.fxml’的内容:

            

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 "/lib/rt.jar" -libraryjars "/lib/javaws.jar" -libraryjars "/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文件现在看起来像这样:

             

问题

现在这个jar子应该真的再次起作用,因为一切都好了。 但它没有! 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 pcstart(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工件被编译为: ./ out / artifacts / JavaFXApp / JavaFXApp.jar

混淆的Jar可以在: ./ out / obfuscated / Obfuscated.jar找到

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

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

对于这个冗长的问题,我很抱歉。 我希望无论如何你会帮助我:)

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

 -classobfuscationdictionary obfuscationClassNames.txt 

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

 A B C D ... 

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

获得例外:

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

但是,如果我看到fxml文件导入更新但不是它们的使用。

 < ? import qA ? > < ? import rA ? >