Sign in to follow this  
Thygrrr

J2ME: All classes in one file versus having them separated?

Recommended Posts

Well, I just started on my new Job as a J2ME mobile games developer today. And I learned from a colleague that it is allegedly better (read: significantly less memory usage) to have the entire source of your app in one class, with local subclasses (EDIT: inner classes) and so on, opposed to having them in separate files and compile them into separate .class files. Is this true? What are the options? [Edited by - Thygrrr on November 28, 2004 5:00:54 AM]

Share this post


Link to post
Share on other sites
Well, having a subclass will produce an extra class file (called SomeClass$1.class or something) thus completely missing the attempted saving.
I personally use three classes, none of which have subclasses defined in them. They are: MIDlet, Canvas and Runnable. I sometimes have a second Runnable class if I have the space to do animated loading screens.
Each class does have a JAR/heap space overhead. This is just the way Java works. Obfuscation does reduce this overhead, mainly by reducing symbol names, but there is still plenty of housekeeping information present so reducing the number of classes will save memory. Some obfuscators can merge orthogonal classes together - but this can result in increased heap usage (more data per instance).
However, some J2ME implementations (early Motorola for example) had limits on the code size of a class so this technique can have upper limits.

Skizz

Share this post


Link to post
Share on other sites
Yeah, Skizz hit the nail, I'll just add some notes:

The extra size per class file ranges between 300 to 500 bytes, I believe. So, this means you should exercise -some- restraint with creating new classes. But often, it's worth spending that 300 to 500 bytes to get nicely organized code. The last Java project I did had 10 different classes.

Also, I've found that code takes up a surprising amount of space. My rough estimate is that every 100 lines of code increases the size of the jar by 600 bytes (this is after obfuscation and after zipping). So by that estimate, if putting some code into a seperate class saves you 100 lines of code, then it's worth it.

EDIT- corrected that estimate I gave.

Share this post


Link to post
Share on other sites
Wow, thanks for the replys! I still have a question, though:

Quote:
Well, having a subclass will produce an extra class file (called SomeClass$1.class or something) thus completely missing the attempted saving.


Speaking of subclass - maybe I used the wrong term, I meant something like this:


class foo
{
class sub_foo
{
}
}


... is this subclassing? At least that's what I meant.

As for the 500 byte overhead: Lets see. 500 bytes 'on disk' are bad, 500 bytes of extra heap memory lost are actually nothing to worry about, unless the game is fairly complex - and my initial projects won't be complex.

Instead, they'll be simple small apps, e.g. the ubiquitous slide shows, where space matters - cram as many images in as possible - but portability does, as well. Having derived classes so your old code can use your new code will, in my eyes, save you a lot of work and maintenance.

Share this post


Link to post
Share on other sites
Quote:

Speaking of subclass - maybe I used the wrong term, I meant something like this:
class foo
{
class sub_foo
{
}
}

Yes, that's what I thought you meant and that will create a second class file for the inner class, so it's a bit of a no-no for J2ME.

I wouldn't use inheritance for the same reasons, each derived class requires an extra class file.

As for portability, I use the C preprocessor to optimise the source for each platform:

// <platform.hxx> defines CANVAS as either Canvas or FullCanvas depending on
// the platform the application is being built for
#include <platform.hxx>
public class GameCanvas extends CANVAS
{
#include <std_graphics.hxx>
// other stuff
public void paint (Graphics dc) // ok, I've been using GDI too much
{
// DrawGraphic is defined in <std_graphics.hxx>
// which is optimised for each platform
DrawGraphic (dc, x, y, image_id);
}
}


I then use a makefile to build the app:
> make platform=Nokia3650 debug=1 obfuscate=1
which builds the Series 60 debug version with obfuscation. I can also define other stuff as well but I'm sure you get the idea.

Skizz

Share this post


Link to post
Share on other sites
Quote:
Original post by Thygrrr

As for the 500 byte overhead: Lets see. 500 bytes 'on disk' are bad, 500 bytes of extra heap memory lost are actually nothing to worry about, unless the game is fairly complex - and my initial projects won't be complex.


Yeah that's correct, the size of the jar is usually the thing that you have to worry about. A lot of phones, especially the Nokia phones, enforce a 64k jar limit.

Runtime memory is not as bad. Out of the phones that my company supports, the worst one is the Nokia 7210 with 200k of runtime memory. So if your jar is 64k, it's kind of hard to reach that limit. Not impossible though :D

Share this post


Link to post
Share on other sites

class foo {
class sub_foo {
}
}



This is an inner class, and it's a bad idea for J2ME. The compiler adds a *lot* of stuff that you're probably not going to use here, because in Java each sub_foo instance is associated with a containing foo instance, and has access to its members.

If you want the C++ behaviour where sub_foo is just "namespaced within" foo, declare it as static class sub_foo.

Otherwise, your source file organization will have basically no effect on the JAR size, since you're still writing the same classes that do the same things. The exceptions are:

- length of class names matters, since .class files include a lot of that kind of symbolic information. However, any standard optimizer or obfuscator will render that moot.

- packages. Just adding the folder structure to your JAR adds quite a bit of overhead, and then there's the additional overhead of indicating to the code where everything else is located. Just don't do it.

I would say that overall it's better to write things with all the classes that seem appropriate first, and 'draw them together' later. It's a bit of an art, but optimization always is.

Share this post


Link to post
Share on other sites
You really should keep down the use of classes. In our current project (which is a big project, for a j2me game) we have 4 classes. The MIDlet, Canvas(which is runnable) and two for handling game stuff. It would be possible to skip those two that handles the game stuff and put everything in the canvas/runnable class, but you need to draw the line somewhere to keep things memorywice smart but still have a clean code design.

/MindWipe

Share this post


Link to post
Share on other sites
You need to be careful as on some handsets when you hit the 5 class mark there is a noticable lag in the game.

Also try and keep an eye on the amount of threads you have running.

Loads your images as soon as you can! A good place I find is in the constructor of the game canvas class as memory fragmentation is a big problem.

You can get out of memory exceptions when you it seems like there is enough heap left.

If your working with other guys who have been around the block a few times you should be ok. ;)

Share this post


Link to post
Share on other sites
Okay, this all sounds like sensible advice.

Here's my resolution of what I'll do:

a) first and foremost, produce clean, object oriented code trying to get away with as little iffy stuff (static inner classes, etc) as possible

b) as I suspected, resource strings have the potential to account for several KB of memory (although ascii usually packs quite well). I'll try to use loops and generated resource names and well-structured programming to avoid as much overhead here, while also improving code legibility.

c) I don't think I'll exceed the 5 class limit for a while, mostly, it'll be the MIDlet, the Canvas, and up to one or two game objects.

d) try to get around having to build my projects using JBuilder (which is a clunky process, at best), and work with shell scripts and makefiles to actually package the application. This is particularly useful for the slide show project I've been assigned to, because with tools like Imagemagick, you can pretty much automate the process of resizing/cropping all the images, putting them into various .jars depending on the target platform (e.g. Nokia Series 60, Siemens C 55).

Share this post


Link to post
Share on other sites
Quote:
Original post by Thygrrr
b) as I suspected, resource strings have the potential to account for several KB of memory (although ascii usually packs quite well). I'll try to use loops and generated resource names and well-structured programming to avoid as much overhead here, while also improving code legibility.


Data-driven design will be your saviour. ::thumbs up::

Quote:

c) I don't think I'll exceed the 5 class limit for a while, mostly, it'll be the MIDlet, the Canvas, and up to one or two game objects.


Consider trying to make one of those 'game object' classes the really big one instead of the MIDlet or Canvas. Those two are the first that you need to get anything up on the screen at all, so you want them to load quickly (i.e. be small).

Quote:

d) try to get around having to build my projects using JBuilder (which is a clunky process, at best), and work with shell scripts and makefiles to actually package the application. This is particularly useful for the slide show project I've been assigned to, because with tools like Imagemagick, you can pretty much automate the process of resizing/cropping all the images, putting them into various .jars depending on the target platform (e.g. Nokia Series 60, Siemens C 55).


Don't deny yourself access to more powerful scripting languages, either. There are some things better done in .bat (.sh, etc.) and others better done in .py (or .pl). [smile]

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
Don't deny yourself access to more powerful scripting languages, either. There are some things better done in .bat (.sh, etc.) and others better done in .py (or .pl). [smile]


Absolutely. Since I admittedly don't know squat about makefiles, and my bash coding skills are mediocre at best, I decided to go for python!

It seems to turn out nicely - I'm building a collection of scripts that will automatically resize, crop, convert and watermark images from all subdirectories in a given directory according to various cell phone display sizes, and then build platform specific classes and packages from them and a shared source with #ifdefs in it.

It's also a good exercise, because I'm not an expert at python, either. I'm mostly a C++ person. Well, was! :D

Share this post


Link to post
Share on other sites
Quote:
Original post by Thygrrr
Update:

I've found that, when developing for J2ME, Apache Ant and the Ant plugin Antenna kick major multi serious ultra buttage! :-D Woot!

I'm really happy with those two pieces of software, though I'll make a mental note to look into J2ME Polish, which is also a plugin for Ant.


Although I did like how you could build and try your apps using ant/antenna it procduces biggers JARs then the j2me wtk, hence I stopped using it.

/MindWipe

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this