Friday, June 09, 2006

J2ME Polish: obfuscator bug

This bug has been the bane of my life for the past few weeks. To a non-IT person (that's a lot of you and I, before my company started), it might have seemed strange to want to obfuscate anything!

The American Heritage® Dictionary defines obfuscate as:
1. To make so confused or opaque as to be difficult to perceive or understand
2. To render indistinct or dim; darken

For people who gets irked when their code gets lifted, obfuscation can be done on their codebase. In J2ME, obfuscation helps to reduce the final JAR size by eliminating classes which have been declared but never referenced, at the same time renaming classes to one-letter or two-letter names, thus 'obfuscating' it for the code thief. It is a nearly standard practice, and I would like to document my little tête-à-tête (or a wrestle?) for others whose search take them here.

Description: J2ME Polish v1.2.4 seems to have a problem obfuscating code which contains the javax.microedition.media.Manager class.

Should we abandon Polish? What if your codebase has grown dependent on Polish? What if, worse, you've fallen in love with Polish' elegant UI? Both were true for me. So here's what I did:

1. Don't obfuscate
No go. I absolutely need two library JARs, one for floating-point-decoding operation (33KB), the other for xml parsing (kxml2-min.jar—18KB). Total JAR size was 295KB. Costs a bomb to download OTA. How can we ever hope anyone would download it to their phone?

2. Manually prune my code & optimize images
Eclipse helps me to see what methods and variables are not being used. I also renamed packages, methods, variables and packages to use shorter names while trying to remember their mnemonics! Basically, all the 'good programming practices' taught in school have to be thrown out of the window when it comes to making lean codes for mobile phones. I only have two 1-KB image files. My effort reduced the JAR size to 188KB.

3. Attempt to implement my UI using Canvas
This took me two days: euphoria and dypshoria took turns when it worked smoothly on Nokia 6230i and then I realized I might have to provision customization for every single phone model!

4. Attempt to fix it
I suspected this bug might be due to two JAR files used by J2ME Polish containing the Manager class in the same package javax.microedition.media. So I bravely combined the two JAR files and replaced the Manager class in Polish' JAR files with the original Sun Wireless Toolkit's. Didn't work.

5. Use Proguard's parameters in J2ME Polish
I tried introducing some parameters "-dontskipnonpubliclibraryclasses", "-dontusemixedcaseclassnames" and "-keep" on the Manager class, in the obfuscator element of the build.xml file. Didn't get past step one, because it requires me to overwrite a Polish obfuscator class.

6. Upgrade to J2ME Polish v1.3-beta4
Not only this version doesn't solve the problem, it introduces new bugs for the function Display.setCurrent(Alert, Displayable)

7. Use alternative obfuscators
Jode, or Retroguard both didn't work with v1.2.4 and v1.3-beta4.

8. Upgrade to ProGuard v3.4 or v3.6
Didn't work. These two versions are not backward-compatible with the calls that Polish v1.2.4 make.

9. Finally, (THIS WORKED!) Obfuscate outside J2ME Polish
I compiled the JARs in Polish for some fifty phone models without obfuscation. Open them using other Wireless Toolkits (Sun's, Siemens' or Sony Ericssons'), attach the source and the library JARs independently, rebuild with obfuscation (Proguard v3.2—same version as what Polish uses)! Smooth as butter. Extra patience required.

RESULT: Final JAR sizes are between 95KB to 106KB (depending on device models).

Talk about dismantling the whole building just to fix a little plumbing problem. What one wouldn't do for something one loves... Hope this helps, folks!

1 comment:

Gilles said...

Hey!

Insightful post... two years later, I'm stuck with the same problem you have.

Do you have any update? Do you style use polish and an obfuscator? Did you make progress in automation?

Cheers,
Gilles