Obfuscate Your JavaFX Application
Join the DZone community and get the full member experience.
Join For FreeIntroduction
JavaFX currently has a high momentum and enjoys good adoption in the community. With its rich set of controls, CSS styling, good and free tool chain and, last but not least, its multi-platform availability (with Version 2.2 that was released just a couple of days ago, it is available for Windows, Mac OS and Linux) it is just natural to take it into consideration when thinking about an implementation technology for commercial desktop applications.
Java is compiled into a bytecode which can be just as easily decompiled back into human readable source code. If you are thinking about writing a commercial application you might want to protect your intellectual property by implementing some functionality that checks if the user has a proper license - for instance a valid serial number - or something alike. This functionality or the whole application should not be easy to decompile and understand by a third party. A common measure to achieve this, or at least make it harder, is obfuscation.
Since the reinvention of Version 2.0, JavaFX is 100% Java, which means you can use any Java obfuscator and just mind some minor differences. There is a whole bunch of free and commercial obfuscation tools out there. One of them you will encounter if you Google java obfuscation, and its proguard (http://proguard.sourceforge.net/). It is free and, although it takes some time to get into it, it's well-documented and ships with an ant task.
The following text describes the process of obfuscating a JavaFX application with proguard. It is a complete example that uses the latest tools and features in JavaFX, including FXML. The following tools were used:
- Netbeans 7.2
- Scene Builder 1.0
- JDK 7 update 6 with JavaFX 2.2
- Proguard version 4.8
The complete example is attached as a netbeans project.
The Application
The example application is a very simple one. It shows one screen with a textfield for a message and a button. If the user presses the button, the message is encrypted and shown in another non-editable textfield. The screen is implemented using fxml (Sample.fxml) and a controller class (SampleController.java).
The code to encrypt the message is implemented in a separate class (EncryptionService.java) and the finally there is an application class with a main method (ObfuscationExample.java) that starts up the whole application. The following screenshot shows the application.
Obfuscation
Proguard is highly customizable and ships with a gui that let's you edit the configuration file that is specific for your application. I don't want to get too much into details here. As mentioned the proguard documentation is pretty exhaustive. You have to specify the jars that you want to get obfuscated (injars) , the resulting jar (outjars) and all libraries that are referenced from your injars (library jars), in any case the Java runtime (rt.jar) and the JavaFX runtime (jfxrt.jar). Until there it is just like any other java application that you obfuscate. In the case of JavaFX, there are some more things that need to be considered:
- In the controller class for the fxml file action handler methods and controls are annotated with the @FXML annotation. You want to keep these annotations and achieve this with the -keepattributes option
- Both controls and action handler methods are connected via the annotation AND their name. Therefore you also want to keep the names of those, which can be achieved with the -keepclassmembernames option that is applied to everything that is annotated with @javafx.fxml.FXML
- Last but not least, you want to keep your main method(s) that are the entry point to your application. In the case of JavaFX you have to configure this always for two classes:
- com.javafx.main.Main
- and your JavaFX application class, in our case: obfuscationexample.ObfuscationExample
-injars dist\ObfuscationExample.jar -outjars dist\o_ObfuscationExample.jar -libraryjars <java.home>/lib/rt.jar -libraryjars <java.home>/lib/jfxrt.jar -dontshrink -dontoptimize -flattenpackagehierarchy '' -keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod -adaptresourcefilecontents **.fxml,**.properties,META-INF/MANIFEST.MF -keepclassmembernames class * { @javafx.fxml.FXML *; } # Keep - Applications. Keep all application classes, along with their 'main' # methods. -keepclasseswithmembers public class com.javafx.main.Main, obfuscationexample.ObfuscationExample { public static void main(java.lang.String[]); }
The result of the obfuscation can be viewed in a decompiler. I was using JD-GUI (http://java.decompiler.free.fr) which is also free and quite easy to use.
Automatically obfuscate during build
After we have the obfuscation setup to our needs, we finally want to integrate it in our build-process. The build.xml that is created automatically in Netbeans offers some hooks to call additional tasks during the build-process -post-jfx-jar seems to the right step, as this is called after the jar file was created. As mentioned above proguard ships with an ant task that allows - besides other things - to just simply execute a proguard configuration file. The target below is called during the build process and does the following:
- Define the proguard ant task
- Call proguard with our configuration that we have setup before
- Rename the resulting obfuscated jar to the original name to make for example the original JNLP-file still work.
<target name="-post-jfx-jar"> <!-- obfuscate and optimize by ProGuard --> <taskdef resource="proguard/ant/task.properties" classpath="lib/proguard.jar" /> <proguard configuration="proguard_config.pro"> </proguard> <move file="${dist.jar.dir}/o_${ant.project.name}.jar" tofile="${dist.jar}" verbose="true" overwrite="true" /> </target>
Conclusion
Although it took me some time to get everything working especially when using FXML, it is after all not much code to get your JavaFX application at least basically obfuscated in a seamless and automated way. Proguard has much more options to obfuscate in a more sophisticated way and to even shrink and optimize your code. Anyway I leave it up to you to configure it to your special needs.
Opinions expressed by DZone contributors are their own.
Comments