Common tricks to optimising Java with examples from the JDK

Overview

While best practices for programming in Java have moved improved over the years, the code base for the OpenJDK has some sections which are very old. They have some best practices but also some good examples of what not to do.

Don't create objects needlessly

Using a object pool doesn't help as much as it did pre-Java 5.0 however that doesn't mean a simple pool won't help. For this reason many of the wrapper classes use a cache for their values, introduced in Java 5.0. This is used by auto-boxing to reduce the overhead of creating objects.

One class which has always had a cache is Boolean. There is only two possible values and they are immutable, so you would think there is never a good reason to create one. This doesn't store many methods in the OpenJDK doing just that.

This class can be used when you get a boolean field via reflection.
class UnsafeBooleanFieldAccessorImpl extends UnsafeFieldAccessorImpl {
    public Object get(Object obj) throws IllegalArgumentException {
        return new Boolean(getBoolean(obj));
    }
with autoboxing, a shorter and more efficient approach would be to have
class UnsafeBooleanFieldAccessorImpl extends UnsafeFieldAccessorImpl {
    public Object get(Object obj) throws IllegalArgumentException {
        return getBoolean(obj); // use the Boolean cache of TRUE and FALSE.
    }
If you don't like auto-boxing, using the appropriate valueOf method

Instead of
public ParameterBlock add(byte b) {
        return add(new Byte(b));
    }
use the valueOf of the wrapper class.
public ParameterBlock add(byte b) {
        return add(Byte.valueOf(b));
    }
The JDK caches every possible Byte value.

What else is there?

After writing up this one example, I realise there is too much to cover in one entry so I will write a series of articles to follow.

Comments

Popular posts from this blog

Low Latency Microservices, A Retrospective

Unusual Java: StackTrace Extends Throwable

System wide unique nanosecond timestamps