问题描述
我正在尝试模糊我的JavaFX应用程序,但它失败了。生成的结果不起作用,我不明白为什么。生成的jar只是失败,因为fxml文件不能再加载所有导入(ClassNotFoundException)。
I'm trying to obfuscate my JavaFX application but it fails. The generated result does not work and I do not understand why. The resulting jar just fails because the fxml file cannot load all imports anymore (ClassNotFoundException).
- 构建可运行的jar(在IntelliJ knwon中作为工件)
- 使用ProGuard对jar进行模糊处理
- 修复一些问题在ProGuard无法做到的那个罐子里
1)最小的示例应用程序
1) The minimal example application
The example application 'GuardTest' is a IntelliJ project that consists of 3 classes.
- sample.Main:包含应用程序入口点和加载GUI fxml文件'sample.fxml'
- sample.Controller:'sample.fxml'的控制器类
- controls.CustomControl:A从HBox继承的简单javafx控件。这用于'sample.fxml'
'sample.fxml'的内容:
The contents of '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文件。我使用以下设置:
2) Obfuscation
Now I use ProGuard for the resulting jar file that is generated from the above project. I use the following settings:
-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'具有以下结构:
3) Fixing some (obvious) ProGuard failures
The resulting jar file 'Obfuscated.jar' has the following structure:
**Obfuscated.jar**
- META-INF
--> MANIFEST.MF
- p
--> a.class
--> b.class
--> c.class
- sample
--> sample.fxml
主类通过加载带有以下内容的'sample.fxml'文件来启动GUI line:
The main class starts the GUI by loading the 'sample.fxml' file with the following line:
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
因为我必须将'sample.fxml'文件移动到文件夹p以及使上面的行重新工作。我还修复了fxml文件中的一些问题,其中ProGuard忘记更改(现在混淆的)类名。
Because of that I have to move the 'sample.fxml' file to the folder p as well to make the above line work again. I also fix some issue in the fxml file where ProGuard forgets to change a (now obfuscated) class name.
现在结构如下所示:
**Obfuscated_fixed.jar**
- META-INF
--> MANIFEST.MF
- p
--> a.class
--> b.class
--> c.class
--> sample.fxml
sample.fxml文件现在如下所示:
The sample.fxml file now looks like this:
<?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')。为什么会这样?
The Problem
Now this jar should really work again because everything is ok again. But it DOESN'T! The fxml loader fails to load the CustomControl (now named/obfuscated 'a.class'). Why is that?
启动jar文件时我得到以下错误输出(我正在运行java版本1.8.0_40):
I get the following error output when starting the jar file (I'm running java version 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):
Here you can find the example project (IntelliJ):https://www.dropbox.com/s/ot51spvwk6lzo4k/GuardTest.zip?dl=0
IntelliJ生成的jar工件编译为:
./ out / artifacts / JavaFXApp / JavaFXApp.jar
The generated jar artifact by IntelliJ is compiled to:./out/artifacts/JavaFXApp/JavaFXApp.jar
混淆的Jar是发现在:
./ out / obfuscated / Obfuscated.jar
The obfuscated Jar is found under:./out/obfuscated/Obfuscated.jar
混淆但固定(至少应该是)jar如上所述:
./ out / obfuscated / Obfuscated_fixed.jar
The obfuscated but fixed (at least it should be) jar as described above:./out/obfuscated/Obfuscated_fixed.jar
并显示'示例中的import语句.fxml'文件导致问题我从fxml文件中删除了我的自定义控件并将其保存到(工作)jar:
./ out / obfuscated / Obfuscated_fixed_work.jar
And to show that the import statement in the 'sample.fxml' file causes the problem I removed my custom control from the fxml file and saved that to the (working) jar:./out/obfuscated/Obfuscated_fixed_work.jar
对不起这个长期问题我很抱歉。我希望无论如何你会帮助我:)。
I'm sorry for the long question. I hope you will help me anyway :)
推荐答案
我找到了解决方案!问题是FXML无法导入不以大写字母开头的类。因此,必须提供ProGuard用于混淆的可用名称的自己的列表。这可以通过以下方式完成:
I have found the solution! The problem is that FXML cannot import classes that do not start with an upper case letter. Therefore one has to provide an own list of available names that ProGuard uses for obfuscating. This is done by:
-classobfuscationdictionary obfuscationClassNames.txt
使用obfuscationClassNames.txt包含可用类名的行分隔列表:
With obfuscationClassNames.txt containing the line seperated list of available class names:
A
B
C
D
...
这篇关于ProGuard打破了JavaFX应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!