Java Performance Tuning
Java(TM) - see bottom of page
Our valued sponsors who help make this site possible
JProfiler: Get rid of your performance problems and memory leaks!
Training online: Threading Essentials course
J2ME performance tips
Get rid of your performance problems and memory leaks!
Get rid of your performance problems and memory leaks!
Java tuning tips for J2ME. This is pretty wide-ranging, but mostly focused on
the size of the application. Graphics performance is the next along, then
usability. See also the tips page on user perceptions.
The following pages have their detailed tips extracted below
The following detailed tips have been extracted from the raw tips page
Optimizing hash functions: generating a perfect hash function (Page last updated January 2001, Added 2001-02-21, Author Jack Shirazi, Publisher OnJava). Tips:
- Minimal perfect hash maps do not require any excess memory, but may impose significant overheads on the map.
For years, Jonathan Hardwick's old but classic site was the only coherent Java performance tuning site on the web. He built it while doing his PhD. It wasn't updated beyond March 1998, when he moved to Microsoft, but most tips are still useful and valid. The URL is for the top page, there are another eight pages. Thanks Jonathan. (Page last updated March 1998, Added 2000-10-23, Author Jonathan Hardwick, Publisher Hardwick). Tips:
- If size is a constraint: use SDK classes wherever possible; inherit whatever possible; put common code in one place; initialize big arrays at runtime by parsing a string; use short names;
"Cutting Edge Java Game Programming". Oldish but still useful intro book to games programming using Java. (Page last updated 1996, Added 2001-06-18, Author Neil Bartlett, Steve Simkin , Publisher Coriolis). Tips:
- Use a dissassembler (e.g. like javap) to determine which of various alternative coding formulations produces smaller bytecode.
- To reduce the number of class files and their sizes: use the SDK classes as much as possible; and implement common functionality in one place only.
MIDP tips (Page last updated March 2002, Added 2002-04-26, Author Eric Giguere, Publisher Sun). Tips:
- Make HTTP requests in a background thread.
- Use an asynchronous messaging model.
- Use WBXML to compress XML messages.
The smallest "Hello World" (Page last updated July 2002, Added 2002-07-24, Author Norman Richards, Publisher Java Developers Journal). Tips:
- Use the -g:none option to strip debugging bytes from classfiles.
- Most bytes in Java class files are from the constant pool, then the method declarations. The constant pool includes class and method names as well as strings.
- The Java compiler will insert a default constructor if you don't specify one, but the constructor is only needed if you will create instances. You can remove the constructor if you will not be creating instances.
- Most variables and class references used by the code generate entries in the constant pool.
- Reusing already existing constant pool entries for class/method/variable names reduces the class file size.
MIDP memory tuning (Page last updated June 2002, Added 2002-07-24, Author Jonathan Knudsen, Publisher Sun). Tips:
- Use an obfuscator to minimize the size of classes.
- Minimize resource sizes by using as few images as possible, and using fewer colors in the images you do use.
- Use as few objects as possible.
- Dereference objects (set them to null) when they're no longer useful so they will be garbage-collected.
- Catch OutOfMemoryErrors on all allocations, or at least the large ones. Don't let an OutOfMemoryError take your application by surprise.
- MIDlets use three types of memory: program memory, heap, and persistent storage. Each of these may be scarce and they should all be treated with respect.
Benchmarking (Page last updated January 2002, Added 2002-01-25, Author Glenn Coates & Carl Barratt, Publisher Java Developers Journal). Tips:
- In J2ME, software accelerators may improve speed, but they may also consume excessive power compared to a processor that executes Java as its native language.
Mobile & wireless devices (Page last updated April 2002, Added 2002-04-26, Author James White, Publisher Java Developers Journal). Tips:
- Prototype to determine the performance of your device. Wireless transmissions require testing to determine if the transfer rates and processing times are acceptable.
- Attempt to create applications that can accomplish 80% or more of their operations through the touch of a single key/button or the "tap" or touch of the stylus to the screen.
- Trying to manipulate a very small scroll bar on a small screen can be an exercise in hand-eye coordination. Horizontal scrolling should be avoided at all costs. Use "jump-to" buttons rather than scrollbars.
- Try to avoid having the user remember any data, or worse, having to compare data across screens.
- Performance will always be a concern in J2ME.
- Avoid garbage generation: Use StringBuffer for mutable strings; Pool reusable instances of objects like DateFormat; Use System.gc() to jump-start or push the garbage collection process.
- Compile the code with debugging information turned off using the -g:none switch. This increases performance and reduces its footprint.
- Avoid deep hierarchies in your class structure.
- Consider third-party JVMs, many are faster than the Sun ones.
- Small XML parsers and micro databases are available for purchase where necessary.
Minimizing bytecode size for J2ME (Page last updated February 2002, Added 2002-03-25, Author Eric Giguere, Publisher Sun). Tips:
- Eliminate unnecessary features.
- Avoid inner classes: make the main class implement the required Listener interfaces and handle the callbacks there.
- Use built-in classes if functionality is close enough, and work around their limitations.
- Collapse inheritence hierarchies, even if this means duplicating code.
- Shorten all names (packages, classes, methods, data variables). Some obfuscators can do this automatically. MIDP applications are completely self-contained, so you can use the default package with no possible name-clash.
- Convert array initialization from code to extract data from a binary string or data file. Array initialization generates many bytecodes as each element is separately initialized.
Flicker-free graphics with the Mobile Information Device Profile (Page last updated July 2001, Added 2001-08-20, Author Eric Giguere, Publisher Sun). Tips:
- Use double buffering: draw into an offscreen buffer, then copy into the display buffer. Copying buffers is very fast on most devices, while directly drawing to a display sometimes causes users to see a flicker, as individual parts of the display are updated. Double buffering avoids flickering by combining multiple individual drawing operations into a single copy operation.
- Use the Canvas.isDoubleBuffered() method, to determine if double buffering is already automatically used: on some implementations the Canvas object's paint method is already a Graphics object of an offscreen buffer managed by the system. (The system then takes care of copying the offscreen buffer to the display.)
- Use javax.microedition.lcdui.Image class to create an offscreen memory buffer, and use Graphics to draw to the offscreen buffer and to copy the contents of the offscreen buffer onto the display. The offscreen buffer is created by calling one of the Image.createImage methods.
- Double buffering does have some overhead: if only making small changes to the display, it might be slower to use double buffering.
- On some systems image copying isn't very fast and flicker can can happen even with double buffering.
- Keep the number of offscreen buffers to a minimum. There is a memory penalty to pay for double buffering: the offscreen memory buffer can consume a large amount of memory.
- Free the offscreen buffer whenever the canvas is hidden (use the canvas' hideNotify() and showNotify() methods.)
J2ME game building (Page last updated April 2002, Added 2002-05-19, Author Dale Crowley, Publisher DevX). Tips:
- J2ME device memory and speeds are very limited which affects everything from the data-loading speed to the frame/refresh rate, and seriously limits the ability to animate characters or otherwise rapidly change the screen.
- Smart graphics is important: you need to draw clear, concise images at extremely low resolutions and with very small palettes. Animated characters need dynamic, easily-read poses which avoid kicks looking like a dance steps, or punches looking like an arm waves.
- Use public variables in your classes, rather than using accessors. This is technically bad programming practice but it saves bytecode space.
- Be extra careful to place things in memory only when they are in use. For example, discard an introduction splash screen after display.
- Try to reduce the number of classes used. Combine classes into one if they vary only slightly in behavior. Every class adds size overheads.
- Remember that loading and installing applications into J2ME phones is a relatively slow process.
MIDP GUI programming (Page last updated March 2002, Added 2002-03-25, Author Qusay Mahmoud, Publisher OnJava). Tips:
- Applications with high screen performance needs, like games, need finer control over MIDP screens and should use the javax.microedition.lcdui package which provides the low-level API for handling such cases.
- Always check the drawing area dimensions using Canvas.getHeight() and Canvas.getWidth() [so that you don't draw unnecessarily off screen].
- Not all devices support color. Use Display.isColor() and Display.numColors( ) to determine color support and avoid color mapping [overheads].
- Double buffering is possible by using an offscreen Image the size of the screen. Creating the image:
i = Image.createImage(width, height); Getting the Graphics context for drawing:
i.getGraphics(); Copying to the screen
g.drawImage(i, 0, 0, 0);
- Check with Canvas.isDoubleBuffered(), and don't double-buffer if the MIDP implementation already does it for you.
- To avoid deadlock paint() should not synchronize on any object already locked when serviceRepaints() is called.
- Entering alphanumeric data through a handheld device can be tedious. If possible, provide a list of choices from which the user can select.
Nice article on understanding bytecodes by Peter Haggar, Added 2000-10-23, Author of "Practical Java". Explains why a synchronized method is faster than a functionally identical synchronized block. (Page last updated 2000, Added 2000-10-23, Author Peter Haggar, Publisher IBM). Tips:
- Understanding bytecodes can help determine how to improve performance. It can also help you to create smaller sized class files.
- Use the -g:none option to make files class smaller [or use a better optimizing compiler]
Performance tuning embedded Java (Page last updated August 2001, Added 2001-08-20, Author Vincent Perrier, Publisher OnJava). Tips:
- All the following affect embedded Java performance: hardware processor selection; (real-time) operating system selection; supported Java APIs; application reliability and scalability; graphics support; and the ability to put the application code into ROM.
- Various approaches for boosting bytecode execution speed include: a JIT compiler (usually too big for embedded systems); an ahead-of-time compiler (requires more ROM, may disallow or slowdown dynamically loaded classes); a dynamic adaptive compiler (half-way house between last two options); putting the Java application code into ROM; rewriting the JVM interpretation loop in assembly; using a Java hardware accelerator.
- Use the lightweight graphical toolkit.
- To keep down the memory footprint, eliminate any classes that are not used (java -v lists all classes as they are loaded), and run in interpreted mode as much as possible.
- Benchmark results are not necessarily applicable to your application [article reviews the applicability of standard and proprietary benchmarks].
Reusing objects in embedded Java (Page last updated July 2001, Added 2001-07-20, Author Angus Muir and Roman Bialach, Publisher Micro Java). Tips:
- A lot of object creation and destruction can lead to a fragmented heap, which reduces the ability to create further objects.
- Define the bulk of memory you need (buffers, etc.) up-front at initialization, and use object pooling to avoid further creation or destruction of objects.
- Throwing/catching exceptions are tremendously expensive.
- Pooling is not always faster than object creation.
Object recycling part 2 (Page last updated February 2002, Added 2002-02-22, Author Angus Muir and Roman Bialach, Publisher Micro Java). Tips:
- The efficiency of pooling objects compared to creating and disposing of objects is highly dependent on the size and complexity of the objects.
- Object pools have deterministic access and reclamation costs for both CPU and memory, whereas object creation and garbage collection can be less deterministic.
Chapter 2, "Java: Fat and Slow?", of "Java 2 Micro Edition: Professional Developer's Guide" referenced from http://www.microjava.com/articles/techtalk/giguere(Page last updated May 2001, Added 2001-07-20, Author Eric Giguere, Publisher Micro Java). Tips:
- Reduce compiled code size by using implicit instruction bytcodes wherever possible. For example, limiting a method to four or fewer local variables (three on non-static methods as "this" takes the first slot), allows the compiler to use implicit forms of instructions (such as aload, iload, fload, astore, istore, fstore, and so on).
- Similarly numbers -1, 0, 1, 2, 3, 4 ,5 have special bytecodes
- Java class files are standalone - no data is shared between class files. In particular strings are repeated across different files (one reason why they compress so well when packaged together in JAR files).
- An empty class compiles to about 200 bytes, of which only 5 bytes are bytecode.
- There are no instructions for initializing complete arrays in the Java VM. Instead, compilers must generate a series of bytecodes that initialize the array element by element. This can make array initialization slow, and adds bytecode to the class.
- You can reduce bytecode bloat from array initialization by encoded values in strings and using those strings initialize the arrays.
- Explicitly set references to null when they are no longer needed to ensure that the objects can be garbage collected.
- Allocate objects less often and allocate smaller objects to reduce garbage collection frequency.
Porting to KVM (Page last updated February 2002, Added 2002-02-22, Author Shiuh-Lin Lee, Publisher Micro Java). Tips:
- Minimize program runtime size. Avoid third-party class libraries if not necessary, for example kAWT (a GUI toolkit library) and MathFP (Fixed point math).
- Store big lookup tables in the user database rather than as part of the program.
- Call GC functions manually.
- Dispose of Objects; close the database and the network connections as soon as they are no longer needed.
- Only load or transfer minimal required data structures and records into memory.
- Avoid float and double calculations.
- Avoid data conversions: store and use the data in the final required format, or execute conversions on the server.
- Use client caching.
- Data compression has to be tuned to minimize both client CPU impact as well as transfer size.
- Use tabbed panels to hold different groups of information. Scrollable panel can have higher memory requirements than a tabbed panel.
- Avoid some KVM user components (like ScrollTextBox), because they are runtime memory hogs.
- Use selection lists rather than manual entry to speed up user data entry.
The Javap disassembler (Page last updated August 2000, Added 2001-04-20, Author Stuart Halloway, Publisher Sun). Tips:
- [Article describes using the
javap disassembler, useful for identifying exactly what the code has been compiled into].
Good Java practices, some of which are good for performance. (Page last updated January 2001, Added 2001-01-19, Author Dave Jarvis, Publisher JOOT). Tips:
- Reduce code size by: obfuscating code; compression in jar files; excluding the manifest in jar files; reordering variable declarations; eliminating dead code; using protected methods.
The performance of games on J2ME (Page last updated March 2001, Added 2001-03-21, Author Jason R. Briggs, Publisher JavaWorld). Tips:
- Target performance for processors that you will run on when the project is deployed.
- Implementing the ImageProducer interface and setting an image's pixels directly eliminates one or two steps in the MemoryImageSource option and seems to be about 10 percent to 20 percent faster on average.
- Raw frame rate display, without taking account of the time taken to draw an image, runs from 2 frames per second (fps) to 400 fps, depending on processor and JVM. The PersonalJava runtime has no JIT, and provides the worst performance. With a JIT it might be usable.
- [Article includes references to a number of hardware based Java implementations, i.e. Java enabled CPUs.]
Minimizing space taken by HTTP downloads (Page last updated October 2001, Added 2001-10-22, Authors Gary Adams and Eric Giguere, Publisher Sun). Tips:
- Use HttpConnection.getLength() to determine the number of bytes needed to to hold the data from a download.
- Use a ByteArrayOutputStream to accumulate results if the content length is indeterminate.
- The best performance is obtained from a 1.1 compliant webserver using persistent connections.
Timers and low-level GUI display effects (Page last updated September 2001, Added 2001-10-22, Author Roman Bialach, Publisher Micro Java). Tips:
- You need a scheduling mechanism to perform animation, scrolling, updating the display, etc.
- The paint() method on the Canvas is called by the system only if it thinks that it needs to repaint it. So we need another timer to repaint the screen on a regular basis. Use a timer to periodically call repaint().
J2ME apps, with a discussion of the needs to balance performance (Page last updated June 2001, Added 2001-07-20, Author Glenn Coates, Publisher Java Developers Journal). Tips:
- J2ME devices have limited processing power, so performance is important and must be considered for the target device.
- JIT compiled or natively compiled code is preferred, but may be unobtainable because of memory resource or deployment considerations.
- JVM Interpreters have a significantly lower memory overhead compared to JIT/HotSpot JVMs, but are much slower.
- Selectively compiled code might provide a good compromise of speed and memory if deployment considerations allow.
- The application does not need to be lightning fast in order to have a responsive user interface. The perception of speed is important, for example, the user interface should give immediate feedback.
- JVM slection for the J2ME device is pivotal to achieving the required performance.
- Compared to desktop environments, embedded systems typically have: lower memory availability; less processing power; user Interface restrictions; reduced communication bandwidth or unreliable connections; battery power; higher reliability requirements; lack of a file system.
Using Timers (java.util.Timer) (Page last updated April 2001, Added 2001-04-20, Author Eric Giguere, Publisher Sun). Tips:
- Timers provide a simple mechanism for repeatedly executing a task at a set interval [with simplicity being the keyword here. Don't look for anything sophisticated like thread interrupt control].
Last Updated: 2018-02-27
Copyright © 2000-2018 Fasterj.com. All Rights Reserved.
All trademarks and registered trademarks appearing on JavaPerformanceTuning.com are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries. JavaPerformanceTuning.com is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
RSS Feed: http://www.JavaPerformanceTuning.com/newsletters.rss
Trouble with this page? Please contact us