devxlogo

Use Obfuscation to Improve the Size, Performance, and Security of Your J2ME Applications

Use Obfuscation to Improve the Size, Performance, and Security of Your J2ME Applications

bfuscate. According to the Merriam-Webster dictionary, obfuscate is a transitive verb meaning to darken, to make obscure or to confuse. In the software engineering business, obfuscation refers to “the deliberate act of nondestructively changing either the source code of a computer program or machine code when the program is in some compiled or binary form, so that it is not easy to understand or read.” Evidently, the author of this last definition must have seen some of my late-night code and decided that the adjective “deliberate” should be added to the definition lest someone mistake plain-old poor quality coding for obfuscated code. All kidding aside, obfuscation can be a serious tool in Java programming.

In J2ME, obfuscation can help protect applications that are deployed to millions of devices. Importantly, but often forgotten, obfuscation can also help developers with some other equally important issues?namely application size and performance.

These two issues are especially sticky when you’re developing for small mobile devices. However, though this article deals strictly with Micro Edition apps, most Java applications could stand to take advantage of the better security, smaller footprint, and improved performance obfuscation provides. You’ll find out what obfuscation does to J2ME code and why more developers should use obfuscation when delivering applications. You’ll also look at how tools and IDE’s provide obfuscation and see that not all obfuscators are created equal (there are various obfuscation methods of which you may not have been aware).

Why Obfuscate?
There are three reasons why you should consider obfuscation:

  1. Protection of intellectual property
  2. Footprint reduction
  3. Improve runtime performance

Protection of Intellectual Property
You’ve just created that killer J2ME application. You made a deal with a device manufacturer to put your application on millions of cell phones. With your application literally in the hands of so many people, how do you protect your intellectual property? If you think it takes special tools and training to reverse engineer your application, think again. Look inside your Java SDK bin directory. That javap.exe tool in the bin directory is a Java class file dissassembler?provided with the freely available SDK download. Getting a hold of your intellectual property is as easy as getting a hold of your class files and running:

	javap com.mycompany.KillerAppMidlet

Obfuscators help protect your property and make it harder to decompile code. The key and operative words in protection are “make it harder.” Obfuscation is not encrypting your intellectual property with crypto. It only makes the code that comes out of a decompiler like javap.exe harder&3151;often much harder?to understand and reverse engineer. Most of the obfuscator vendors will use the term “nearly impossible” when referring to the ability to reverse engineer code that has been obfuscated with their tool. While nearly impossible is good enough for most applications, it shouldn’t be confused with completely secure.

Footprint Reduction
Somewhere in your object-oriented training, you were probably taught to try to name packages, classes, methods, and fields after the real world things they represented. Instead of names like h, i, and j programmers have opted for names like com.intertechtraining.services.financial, bank_account, getInterest, and interest_level. Though this naming convention is much more human readable and much easier to later maintain or modify, it turns out that all this “natural” naming tends to bloat the byte code that ultimately goes on the devices. Just how much bloat? Results are going to vary depending on your code (how it was written, how much of it is public vs. private, etc.) and what obfuscation tool is used and how it is configured to output code. In a non-scientific experiment, I used NetBeans 4.1 to build four different projects with NetBeans obfuscator on (NetBeans used ProGaurd’s obfuscator) and off. Table 1 shows the results.

Project

Description

Non-obfuscated jar size

Obfuscated jar size

% Reduction

Games

Demo MIDlet Suite provided with WTK 2.2

54.1K

38.7K

28.5%

Obex demo

Demo of Object Exchange provided with WTK 2.2

75.4K

70.7K

6.2%

Web Service Client

J2ME WS client from http://www.devx.com/wireless/Article/28046

11.2K

6.6K

41.3%

Stock Quote Suite

J2ME Stock Quote MIDlet demo from http://www.manning.com/books/white/source

16.6K

11.3K

31.9%

Table 1. Four different projects built using the NetBeans obfuscator.

As you can see, some tools report as much as 70 percent reduction and the overall results suggest that 30-40 percent is normal for most applications. While you cannot always expect to reap a 40 percent reduction in your application, there is a good chance that an obfuscator is going to get you a significant chunk of space back. This has the impact of making it easier to obtain your application over the air and the application will load into memory faster when executed. Or, use the new-found space to build even more features into that killer application.

Improve Runtime Performance
This last benefit, again, depends on your choice in obfuscator and your code structure/functionality. However, several obfuscation vendors report that their techniques of obfuscation actually help improve the performance of the application. In some cases, the performance is improved by as much as 30 percent. PreEmptive Solutions‘ DashO product claims to use “its comprehensive analysis to provide clues to Java runtimes so they can work better.”

In fact, a new set of tools is growing up around the ideas offered by traditional obfuscators. Products such as Innaworks’ mBooster and J2ME Polish offer tools that offer to help optimize your J2ME applications beyond obfuscation.

What Does an Obfuscator Do?
In general, an obfuscator changes the byte code (the code stored in your .class files). What the obfuscator changes and how it determines what to change depends on the obfuscator implementation. There are many obfuscators and each use a variety of byte code transforming methods.

Additionally, obfuscation has changed over time. The first obfuscators (known generally as first generation obfuscators) simply changed the package, class, method, field, and variable names of your code to meaningless strings and removed any comments or debugging information. In a simplified example, all com.intertech.financial.Bank_Account objects get transformed to simple x objects. Second generation obfuscators change the actual control flow (loops, conditionals, etc.). As another simple example, an obfuscator could take a simple statement like acct.setBalance(newBalance) and wrap it with a conditional:

	if (x=0) then {		acct.setBalance(newBalance);	} 	else{		//do something else	}	

The x=0 condition may always be true and the else portion of the statement may never get executed, but it’s tough for someone looking at decompiled code to know that. The runtime outcome of control-modified code should be the same, but tracing the functionality inside a program where the control has been modified is much tougher. Finally, there is data obfuscation whereby actual data structures are altered to further confuse anyone working with decompiled code. Again, a simple example includes increasing or decreasing the size of an array that is used in the code.

Obfuscator vendors today use a combination of these methods and other proprietary methods as well. Hongying Lai has written an excellent and often-referenced paper documenting some of the obfuscation methods and comparing several Java obfuscators that were on the market at the time the article was written in February 2001.

One more thing with regard to obfuscation and J2ME CLDC applications is the consideration of obfuscation before or after preverification. Recall that in limited devices, byte code verification of classes is usually too big of an operation to be done on the devices, so class files are “preverified” or annotated with byte code “properties” when the application is built and readied for deployment. The KVM on a J2ME CLDC device checks the class files for the preverification “properties.”

So, how does obfuscation that also modifies the byte codes affect this process? In most cases, obfuscation will be accomplished prior to the preverification step of your development build process. In this case, the obfuscated code is preverified and, when deployed, the KVM is none the wiser. Some tools offer options to obfuscate after preverification. This requires the preverification tool to also update the byte code properties so as not to invalidate the information already inserted by the preverification process.

Obfuscation Warnings
Obfuscation is a helpful tool to reduce the size of a deployed application, prevent outsiders from stealing your work, and possibly making your application perform better. However, nothing in software engineering comes for free and you should also be aware of some potential issues when obfuscating your code.

First, make sure you thoroughly test your obfuscated code. The goal of obfuscation is to scramble your application enough to make decompiling and understanding your application difficult. Sometime, the obfuscator goes a bit too far. Today’s products are good, but occasionally there are cases where the obfuscator stumbles on unforeseen code or the user is not aware of the various coding rules and configuration settings available with most obfuscators and the result is code that will not run when deployed to the device.

Platform independence may be compromised using obfuscation. For example, depending on the implementation, an obfuscator that knows about all the rich features in Java 5.0 may generate code that will not work on lesser JVMs.

Use of reflection tends to be one of the biggest obstacles in obfuscation. If you use a lot of reflection in your application, confer with the obfuscation vendor on potential issues and, in some cases, tips and tricks on how to avoid issues when the obfuscator comes in contact with reflective code.

Some methods of obfuscation actually increase the size of the application and/or reduce performance. In an exaggerated case, imagine what would happen if each line of code was surrounded by psuedo-conditional statements to effect control obfuscation? Check the size and performance of your obfuscated code to insure you are getting the benefits of obfuscation and not suffering from the opposite.

Obfuscation Implementation
Turn to your favorite Internet search and type “Java Obfuscation” and you will find dozens of obfuscators. Click here for a list of obfuscators to get you going.

Two of the most popular open source obfuscators are ProGuard and RetroGuard. On the commercial side, PreEmptive Solution’s DashO and Zelix KlassMaster Java Obfuscator are both well-touted Java obfuscators that also seem to understand and document special J2ME issues associated with obfuscation.

Most of the well known IDEs also offer built in obfuscators. NetBeans 4.1 with Mobility Pack comes with the open source ProGuard obfuscator already built in. In fact, obfuscation can be made part of the normal build process. Right click on any J2ME project in NetBeans and request properties from the resulting menu option. In the Properties window, one of the build options is “Obfuscating.” You have a slide bar dial that allows you to turn obfuscation on and off and to set the level of obfuscation when on (see Figure 1). A setting of two causes just private fields and methods to be obfuscated while a setting of nine causes “everything except public methods of MIDlet classes” to be obfuscated.


Figure 1. NetBeans Obfuscation Configuration: Obfuscation is easily made part of the build process by simply setting the level of obfuscation in the project properties.
 
Figure 2. Stubs for Obfuscators: When not immediately available, most IDEs provide the means to add an Obfuscator, as do Eclipse and the Wireless Toolkit. The Wireless Toolkit is shown here.

Both EclipseME and the J2ME Wireless Toolkit (now called the Sun Java Wireless Toolkit with release 2.3) are equipped to use the ProGuard obfuscator as well, but ProGuard must be downloaded and configured separately. Help with how to configure the obfuscator with the Wireless Toolkit is available here.

Obfuscating the Obvious
No, obfuscation is not the panacea solution for all J2ME problems. In some cases, because the IDEs are getting much better at helping us take advantage of all available development improvement options, you may already be obfuscating and you didn’t even know it. If so, great! Now you might also explore what obfuscator you are using and how you have it configured to give you optimal results.

As with all tools, a little research and some trial/error may be in order. But in J2ME, when something offers the promise of a smaller footprint, faster provisioning, possible performance enhancements, and better intellectual property security, I am hard pressed to find a reason not to at least explore it.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist