{"id":168,"date":"2004-08-08T09:15:53","date_gmt":"2004-08-08T15:15:53","guid":{"rendered":"http:\/\/www.mooreds.com\/wordpress\/?p=168"},"modified":"2004-08-08T09:15:53","modified_gmt":"2004-08-08T15:15:53","slug":"decreasing-the-size-of-a-midlet-jar","status":"publish","type":"post","link":"https:\/\/www.mooreds.com\/wordpress\/archives\/168","title":{"rendered":"Decreasing the size of a midlet jar"},"content":{"rendered":"<p>The J2ME application I have been working on has been ready for testing for quite some time, but I didn&#8217;t want to get a new AT&amp;T phone.  For J2ME, you really need a GSM phone&#8211;I don&#8217;t think any of the older TDMA models support it.  But the <a href='http:\/\/www.attwireless.com\/global\/maps\/coveragemap.jhtml?zip=98052&amp;map=Y&amp;zipInput=Y&amp;mapDisplay=df'>GSM network coverage<\/a> doesn&#8217;t match the coverage of the TDMA network&#8211;especially out west (aside: isn&#8217;t that magnifying glass pretty cool?).  So I put off buying a phone until my summer road tripping was done.  <\/p>\n<p>I&#8217;ve had a Nokia 6160 for almost 4 years.  Even though friends mocked the size of it, it was a great phone&#8211;durable, good talk time.  I thought I&#8217;d try another Nokia, and got one of the lower end GSM phones, the <a href='http:\/\/www.forum.nokia.com\/main\/0,6566,016-1337,00.html'>6200<\/a>.    This supported J2ME, and weighed maybe half as much.  I was all stoked to try the application on my brand new phone.<\/p>\n<p>I started download the jad file, and was getting &#8216;File Too Large&#8217; errors.  A couple of searches later, I found Nokia&#8217;s <a href='http:\/\/www.forum.nokia.com\/main\/0,,015-Java-1-5,00.html#matrix'>developer device matrix<\/a> which is much more useful than the User Guide or the <a href='http:\/\/www.nokiausa.com\/phones\/6200\/1,2803,feat:1,00.html'>customer facing description of phones<\/a>.  Whoops.  Most of the Series 40 (read: affordable) Nokia devices only supported J2ME applications which were, when jarred up, less than 64K in size.  <\/p>\n<p>Our application, however, was about 78K.  This highlights one of the differences between J2ME and J2SE\/J2EE.  When coding in the latter world, I was never concerned about code size&#8211;getting the job done quickly was paramount, and if I needed to use 13 libraries which bloated the final size of my application, I did.  On a cell phone, however, there&#8217;s no appeal to adding memory or changing the JVM configuration to optimize memory use.  If the Nokia phone only accepts jars of 64K or less, I had three options:<\/p>\n<p>1.  Write off the Nokia Series 40 platform.  Ugh&#8211;I like Nokias, and other folks do too.<\/p>\n<p>2.  Do some kind of magic URL classloading.  This seemed complicated and I wasn&#8217;t sure how to do it.<\/p>\n<p>3.  Decrease the size of the jar file.<\/p>\n<p>Now, the 78K jar had already been run through an <a href='http:\/\/proguard.sourceforge.net\/'>obfuscator<\/a>.  I wasn&#8217;t going to get any quick and easy gains from automated software.  I posted a question on the <a href='http:\/\/www.javaranch.com'>JavaRanch<\/a> J2ME forum and received <a href='http:\/\/saloon.javaranch.com\/cgi-bin\/ubb\/ultimatebb.cgi?ubb=get_topic&amp;f=41&amp;t=002400'>some useful replies<\/a>.  Here&#8217;s the sequence I went through:<\/p>\n<p>1.  Original size of the application: 79884 bytes.<\/p>\n<p>2.  Removal of extra, unused classes: 79881.  You can see that the obfuscator did a good job of winnowing out unused classes without my help.<\/p>\n<p>3.  Changed all the data objects (5-6 classes), which had been written in classic J2SE style with getters and setters for their properties, to have public variables instead:  79465<\/p>\n<p>4.  Combined 3 of the data object classes into one generic class: 78868<\/p>\n<p>5.  Combined 5 networking classes into 2: 74543<\/p>\n<p>6.  Removed all the logging statements: 66044.  (Perl to the rescue&#8211;<code>$ perl -p -i -e 's!Log\\.!\/\/Log.!' `find . -name \"*.java\" -print |xargs grep -l 'Log\\.'`<\/code>)<\/p>\n<p>7.  Next, I played around with the <a href='http:\/\/jode.sourceforge.net\/'>jode<\/a> obfuscator which <a href='http:\/\/www.enterprisej2me.com'>Michael Yuan<\/a> recommended.  I was able to radically decrease the size of the jar file, but, unfortunately, that jar file didn&#8217;t work on the phone.  I also got a ton of exceptions:<\/p>\n<div><code><\/p>\n<pre>java.util.NoSuchElementException\n        at jode.bytecode.BytecodeInfo$1.next(BytecodeInfo.java:123)\n        at jode.obfuscator.modules.LocalOptimizer.calcLocalInfo(LocalOptimizer.java:370)\n        at jode.obfuscator.modules.LocalOptimizer.transformCode(LocalOptimizer.java:916)\n        at jode.obfuscator.MethodIdentifier.doTransformations(MethodIdentifier.java:175)\n        at jode.obfuscator.ClassIdentifier.doTransformations(ClassIdentifier.java:659)\n        at jode.obfuscator.PackageIdentifier.doTransformations(PackageIdentifier.java:320)\n        at jode.obfuscator.PackageIdentifier.doTransformations(PackageIdentifier.java:322)\n        at jode.obfuscator.PackageIdentifier.doTransformations(PackageIdentifier.java:322)\n        at jode.obfuscator.PackageIdentifier.doTransformations(PackageIdentifier.java:322)\n        at jode.obfuscator.ClassBundle.doTransformations(ClassBundle.java:421)\n        at jode.obfuscator.ClassBundle.run(ClassBundle.java:526)\n        at jode.obfuscator.Main.main(Main.java:189)\n<\/code><\/pre>\n<\/div>\n<p>I'm sure I just didn't use it right, but the jar file size was so close to the limit that I abandoned jode.<\/p>\n<p>8.  Instead, I put all the classes in one file (perl to the rescue, again) and compiled that: 64057 bytes.  The jar now downloads and works on my Nokia 6200 phone.  <\/p>\n<p>When I have to do this again, I'll definitely focus on condensing classes, basically replacing polymorphism with <code>if<\/code> statements.  After removing extraneous Strings and concatenating all your classes into one .java file (both of which are one time shots), condensing classes is the biggest bang for your buck.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The J2ME application I have been working on has been ready for testing for quite some time, but I didn&#8217;t want to get a new AT&amp;T phone. For J2ME, you [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,6],"tags":[],"class_list":["post-168","post","type-post","status-publish","format-standard","hentry","category-java","category-programming"],"_links":{"self":[{"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/posts\/168","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/comments?post=168"}],"version-history":[{"count":0,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/posts\/168\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/media?parent=168"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/categories?post=168"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/tags?post=168"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}