Obfuscating Your MIDlet Suite

by C. Enrique Ortiz

If you are encountering size restrictions in Over-the-Air (OTA) provisioning for your MIDlet suite, you have a couple of options. This tech tip describes one of them: obfuscating your MIDlet suite to help reduce the MIDlet suite application size.

Obfuscating the JAR

Code obfuscation is the process of "obscuring" Java classes with the purpose of making them harder to decompile back into source (reverse-engineer). Obfuscation typically entails renaming classes, methods and fields to use shorter names, effectively reducing the size of Java class. Some obfuscators go beyond just obfuscating and also implement bytecode optimization and shrinking techniques.

The Sun Java Wireless Toolkit provides support for third-party obfuscation. You can also add an obfuscation build step to your Ant build scripts. Both approaches are covered next.

The Java Wireless Toolkit

The Java Wireless Toolkit uses a plug-in architecture to support third-party obfuscators. Some popular third-party obfuscators are ProGuard, RetroGuard, and DashO. The WTK is configured by default for ProGuard, but you must first download ProGuard, extract the proguard.jar file, and copy it into the WTK/bin directory.

To use RetroGuard, the WTK property file ktools.properties must be updated. This property file can be found under the WTK installation directory. The following snippets show the default ktools.properties configuration file values, and how to change these to support other obfuscators:

obfuscator.runner.class.name: com.sun.kvem.ktools.RunPro obfuscator.runner.classpath: wtklib/ktools.zip

The ProGuard default configuration, which specifies default switches for the obfuscator such as what classes to keep untouched, can be found at proguard/wtk/default.pro inside the proguard.jar.

To support a different version of ProGuard, download it from the website, and copy it into WTK/bin as indicated above. Or, you can change the default configuration to point directly to ProGuard:

obfuscator.runner.class.name: proguard.wtk.ProGuardObfuscator
obfuscator.runner.classpath: [path-to-jar]/proguard.jar

There are some benefits to the above, including a more efficient use of ProGuard because the ProGuard engine is invoked directly instead of in a separate virtual machine.

To use the default RetroGuard configuration:

obfuscator.runner.class.name: com.sun.kvem.ktools.RunRetro 
obfuscator.runner.classpath: wtklib\\\\ktools.zip

To support other obfuscators such as DashO, an obfuscator plug-in must be written. For more information see the Sun Java Wireless Toolkit Basic Customization Guide that comes with the WTK documentation.

Once the WTK has been properly configured, you can create an obfuscated package for your project by going to Project->Package->Create Obfuscated Package, as illustrated next:

Figure 1: MashupMapPortlet Figure 1: Creating an Obfuscated Package

Create Obfuscated Package will compile, obfuscate, and deploy your project.

Here's how to use obfuscator from an Ant build script.

Ant Script

If you have a standalone build process for your MIDlet that uses Ant, you can add an obfuscation build target to your Ant build.xml script.

You can use the ProGuard-provided Ant tasks for Ant version 1.6.0 or higher. First, define the proguard task as follows:

<property name="buildjars.home" location="lib/thirdparty"/>
:

<taskdef resource="proguard/ant/task.properties" classpath="${buildjars.home}/proguard.jar" />

The above task definition will use the specified resource file, found inside the proguard.jar file and which defines the task name and classpaths.

Once the task has been defined, it can be invoked as shown in the following example build.xml snippet:

<target name="obfuscate" depends="javacompile" description="Obfuscate compiled classes">
    <jar jarfile="${temp.jar}">
        <fileset dir="${unpreverified.classes}"/>

    </jar>

    <proguard>
        -injars ${temp.jar}
        -outjar ${obfuscated.jar}
        -libraryjars ${midp.jar};${cldc.jar}
        -overloadaggressively
        -defaultpackage ''
        -allowaccessmodification
        -dontusemixedcaseclassnames            
        -printmapping obfuscation-map.txt
        -keep public class \* extends javax.microedition.midlet.MIDlet
    </proguard>

    <unjar src="${obfuscated.jar}" dest="${obfuscated.classes}"/>
</target>

The above snippet is part of a large build.xml, and depends on other build targets such as javacompile, which creates an intermediate temp.jar that is an input to the obfuscation step. The obfuscate build target generates obfuscated.jar used to generated the final MIDlet suite JAR file.

While the above is the preferred method for using ProGuard with Ant, you don't have to use the ProGuard-provided Ant task-you can define your own:

<target name="obfuscate" depends="javacompile" description="Obfuscate compiled classes">
    <jar jarfile="${temp.jar}">
        <fileset dir="${unpreverified.classes}"/>
    </jar>
    <java jar="${buildjars.home}/proguard.jar" fork="true" failonerror="true">

        <arg line="-printmapping obfuscation-map.txt"/>
        <arg line="-libraryjars ${midp.jar};${cldc.jar};${wma20.jar}"/>
        <arg line="-injars ${temp.jar}"/>
        <arg line="-outjar ${obfuscated.jar}"/>
        <arg line="-keep 'public class \* extends javax.microedition.midlet.MIDlet'"/>
    </java>

    <unjar src="${obfuscated.jar}" dest="${obfuscated.classes}"/>
</target>

But again, using the ProGuard-provided Ant task is the preferred method.

RetroGuard also provides a set of Ant tasks that you can use in your build.xml file. As with ProGuard, the first thing to do is define the Ant task:

<taskdef name="RetroGuardTask" classname="COM.rl.ant.RetroGuardTask"/>

Following the previous ProGuard example, the following snippet shows how to use the RetroGuard Ant task:

<target name="obfuscate" depends="javacompile" description="Obfuscate compiled classes">
    <jar jarfile="${temp.jar}">
        <fileset dir="${unpreverified.classes}"/>
    </jar>

    <RetroGuardTask 
        infile=${temp.jar} 
        outfile=${obfuscated.jar}
        rgsfile="rg-script-file.log"
        logfile="retroguard.log" 
    /> 

    <unjar src="${obfuscated.jar}" dest="${obfuscated.classes}"/>

</target>

Where temp.jar and obfuscated.jar is as explained above, rg-script-file.log is the RetroGuard script file that specifies the classes, methods, fields, and attributes to be preserved from obfuscation, and retroguard.log is the output obfuscation log file.

Conclusion

In conclusion, you should always obfuscate your code. Obfuscating your code not only will reduce the size of your application, but can optimize it as well. You can use Ant to build and obfuscate your code. In addition, the Sun Java Wireless Toolkit, which provides support for third-party obfuscators and a plug-in architecture to add support for new obfuscators, can be used in conjunction with the NetBeans IDE.

Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

Tips for developers who use Java technologies (Java SE, Java ME, JavaFX) for mobile and embedded devices.

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today