Win a copy of Mesos in Action this week in the Cloud/Virtualizaton forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Decreasing size of jar file

 
Daniel Moore
Ranch Hand
Posts: 31
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello,

I'm trying to target the Nokia 6200 with my application. Unfortunately, my application is about 70K when jarred up. According to this page, this device only excepts jar files of 64K. (I'm hoping they're being precise, and mean 65536 bytes, rather than 64000.)

I have done the following to decrease the app's size:

1. Used an obfuscator: proguard 2.0.1 and 2.1 (no size difference, fyi). I'm building with Sun's WTK 2.0.1 on Windows.

2. Removed all the log statements, and the logging class. This was the only extraneous class I could find.

3. Removed images in the application.

4. Tried to make as many variables static and final as possible.

Short of rearchitecting the entire program does anyone have any other suggestions to decrease the size of the jar file?

I've googled this, and didn't find anything really useful. I also searched this forum, but didn't find anything really applicable.

Any help would be appreciated.

Thanks,
Dan
 
Daniel Moore
Ranch Hand
Posts: 31
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In case anyone is interested, here are some numbers on my minaturization(sp?) efforts:

Original obfuscated jar file size: 79848
Removed all logging statements: 71572
Removed logging class: 70582
Removed image: 68968
Condensed all classes into one class file: 66959
Removed another unused class: 66953
 
Michael Yuan
author
Ranch Hand
Posts: 1427
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think you can use a more aggressive obfuscator (e.g., JODE). I think proguard only shortens the class names not the package names. If you program contains "how to" instructions, you can consider shorten them as well. Also, I would use high level UI as much as possible to avoid the long paint() methods.
 
Alan Walker
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The Nokia series 40 phones seem to reject a JAR file once it gets to about 63700 bytes I'm afraid. (This is based on experience with the 7210 emulator and the 6610 actual device.)

There is an article on the Sun website, Slimming Wireless Java Applications, that may help you. And there is an article at Forum Nokia called "Efficient MIDP Programming". Often, tips about reducing JAR size are included in articles about J2ME efficiency in general, so searching on terms like "J2ME efficiency" or "J2ME performance" may find some useful items.

One thing to watch out for is anonymous inner classes - for multi-threading, for example. It is better if you can make an existing class implement the Runnable interface by giving it a run() method.

Best of luck!
[ August 07, 2004: Message edited by: Alan Walker ]
 
Roseanne Zhang
Ranch Hand
Posts: 1953
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oh, yes, different phones accept different sizes of jars.

I've to make a 291k original app to fit into 128k limit, 100k limit, and 64k limit as well.

The reducing techniques are talked enough on this thread and the links in this thread. What I want to say is when you do the reduction, you need to put those larger jar-size allowence phones in mind as well. You might be ordered to do the opposite sometimes in the future.

All our 128/100/64 kb limits application(s) are using the same code base, only put the differences into phone specific sections.
 
Daniel Moore
Ranch Hand
Posts: 31
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks everyone for the help.

I got the application down to 64080 bytes, and it installed on the 6200 I have.

The things that helped the most to decrease the jar file size, in order:

1. Eliminating logging (which was just System.out.println statements) by commenting it all out:
perl -p -i -e 's!Log\.!//Log.!' `find . -name "*.java" -print |xargs grep -l 'Log\.'`

2. Combining everything into one file.

3. Combining classes where applicable--not great for polymorphism and oo programming.

4. Eliminating accessors on simple data objects.

I tried jode, which cut down the size significantly, but was getting weird errors from the Nokia (bad stack and others). It also didn't play very nice with image and manifest files.

Thanks for all the suggestions.
 
Michael Yuan
author
Ranch Hand
Posts: 1427
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Daniel Moore:
I tried jode, which cut down the size significantly, but was getting weird errors from the Nokia (bad stack and others). It also didn't play very nice with image and manifest files.


I think the bad stack error often occurs when you use getWidth() and getHeight() methods. You can simply hard code the screen size values instead of determining them dynamically. You can configure JODE to avoid resource and manifest file names. But yes, it is troublesome -- that is what you get when you need to do some extreme optimization.
 
Robert Virkus
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

one thing which was not mentioned here is to use preprocessing (instead of hardcoding) stuff. This makes adjustments to devices much more memory-efficient and performant compared to using dynamic class loading or similar.

J2ME Polish includes very powerful preprocessing along with a device database, which makes it really easy.

Another interesting thing is the logging framework of J2ME Polish. With this framework you can
a) use System.out.println() for logging
b) see the logging messages on the actual phone as well
c) turn off or turn on logging for specific classes or packages
d) turn the debugging completely off - absolutely no traces will be left in the application code then.

Example:
[CODE
//#debug
System.out.println("Hello World");
[/CODE]

Find more information about J2ME Polish at www.j2mepolish.org

Best regards,
Robert
 
Jan Filipsky
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello,
we use our own preprocessing tool which uses this technique:
- comments out all system.out.print... and system.err.print...
- finds all public static final variables and converts them into C-like header file eg constants.h (eg #define MILLIS_PER_TICK 100)
- at the top of each .java file it processes it adds #inculude constants.h

then it calls c preprocessor, which replaces all these "constants" with their values.

This technique decreases the resulting JAR size by cca 10%

The reason is that public static final variables are stored in classes in so called constant pool (and that consumes space) and accessing them is also expensive - there is an opcode "get constant nr x from the pool"

On the other hand when you (or preprocessor) use a value (eg. 10) there is only an opcode "use 10"

Sorry for my english, hope it helped
[ August 20, 2004: Message edited by: Jan Filipsky ]
 
Roseanne Zhang
Ranch Hand
Posts: 1953
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Jan Filipsky:
Hello,
we use our own preprocessing tool which uses this technique:
- comments out all system.out.print... and system.err.print...
- finds all public static final variables and converts them into C-like header file eg constants.h (eg #define MILLIS_PER_TICK 100)
- at the top of each .java file it processes it adds #inculude constants.h

then it calls c preprocessor, which replaces all these "constants" with their values.

This technique decreases the resulting JAR size by cca 10%

The reason is that public static final variables are stored in classes in so called constant pool (and that consumes space) and accessing them is also expensive - there is an opcode "get constant nr x from the pool"

On the other hand when you (or preprocessor) use a value (eg. 10) there is only an opcode "use 10"

Sorry for my english, hope it helped

[ August 20, 2004: Message edited by: Jan Filipsky ]


Except the comment out System.out.println(), you really really don't need your preprocessor. All works you described here have been already done by the obfuscator. You probably only add confusion to it.
 
Jarek Foltynski
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have used proguard, and it can reduce the size of jar file greatly. Not only it reduces class files names and packages names, but also can move all classes to main package (means no packages at all). So you probably did not use right options.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic