Skip navigation

Monthly Archives: March 2009

Serialization allows storing (and restoring) objects as streams – allowing them to be saved to disk or sent over network connections.

A class which implements the java.io.Serializable interface will be available to serialize. The interface itself is empty – there are no methods on it, it’s just a marker interface.

If you mark an object as being available for serialization you can use the transient keyword to mark variables which should not be serialized – passwords for instance.

Over time you may make changes to a class which you’re using serialization with. Because of this it’s important to know if we’ve made any significant changes (e.g. changing a field from transient). We use a versioning marker for this which you have probably seen your IDE prompt you to use:

static final long serialVersionUID;

If you restore an object having changed the serialVersionUID then an InvalidClassException will be thrown. If you do not specify the serialVersionUID then a default one will be generated for you. It may be over sensitive to changes to your class though and result in more InvalidClassException errors than may be necessary.

Serialization, while useful where required, is slow. That’s not so much a bad thing as just something to keep in mind.

Also known as Inversion-Of-Control (IOC), dependency injection allows the container or a framework library to inject instances of certain classes into your code directly.

This alleviates the need for factories and use of the new keyword.

There are many different options for dependency injection. Possibly the most common solution is to use the Spring Framework. As a Java developer though I’m not particularly fond of XML configuration, preferring to at least have my syntax checked by a compiler. That’s in no small part why I prefer to use Google Guice for DI, which is also much more lightweight as it’s only targeted at DI where Spring also targets MVC, AOP, etc.

Initializing Guice is relatively trivial:

    ...
    Injector injector = Guice.createInjector(getModule());
    ...

    private Module getModule() {
        return new Module() {
            public void configure(Binder binder) {
                binder.bind(UserService.class).to(UserServiceImpl.class);
            }
        };
    }

Now you can simply inject the UserService implementation into references to the interface like so:

    @Inject
    private UserService userService;

Easy isn’t it? Google Guice have great documentation with lots of examples and detail on why you should be using DI and how it can help testing.

Where you have a situation with multiple threads accessing the same variables data inconsistencies may arise and we need to ensure these sections of code are locked during access that requires no more than one thread to manipulate the data at any one time.

We refer to this single thread data access locking as synchronization.

Entire methods can be synchronized simply by adding the synchronized keyword after declaring the visibility. Alternatively you can lock down smaller areas of code for synchronization and this is likely to yield performance improvements (and hopefully avoid starvation), particularly as it’s an area where we’ve established multiple threads are competing for access to data.

synchronized(this) {
counter++;
}

I suggest deadlocks and Object.wait() in the context of threads if you’re looking for further reading. High Level Concurrency Objects from the Java tutorial is also worth looking at once you’ve mastered the basics.

A Thread is an execution environment with each command being executed in a logical order. If you’ve not yet encountered Threads then the chances are that all your programs have been single threaded.

Threads can be created by extending Thread or implementing Runnable. Extending Thread might be easier in simple applications but implementing Runnable leaves more room for multiple inheritance.

Thread defines certain static methods to control the current Thread. The sleep() method, which throws InterruptedException if the static interrupt() method is called, allows pausing execution for a defined period of time. The join() method allows one Thread to wait for the execution of another to finish.

That’ll do for now. I’ll explore synchronization with respect to threading at some point later.

Exceptions in Java are divided into two groups; checked and unchecked (or runtime) exceptions.

Checked exceptions will extend java.lang.Exception and must be declared in the method signature if thrown.

Runtime exceptions do not need to be declared by throwing methods and either extend java.lang.RuntimeException or java.lang.Error.

Checked exceptions tend to be exceptions you can reasonably be expected to do something about and recover whereas runtime exceptions should be those which cannot be recovered from.

If you’re writing an application dependent upon a database and the database connection can’t be established then that’s likely to be terminal. This should be a runtime exception – it’s ok to blow up over this.

If a single transaction fails then you might expect a checked exception to be thrown, to rollback the transaction and allow program execution to continue.

Strong references are the type you will be most used to.

SomeFinalObject target = new SomeFinalObject();

Here a strong reference is stored in the target variable.

The SomeFinalObject class is final, as the name suggests. If we now want to record information about our target object and the property isn’t available to set on it, then we may map our target object to this property.

propertyXHashMap.put(target, propertyX);

Now we have another strong reference to our target object, in the HashMap. So even if we’re done using the target object, if our propertyXHashMap instance still exists and has this strong reference then our target object will never be garbage collected. This will gradually increase memory usage, potentially never releasing it.

A weak reference however will not prevent an object being garbage collected.

WeakReference weakRef = new WeakReference(target);

propertyXHashMap.put(weakRef, propertyX);

Using weakRef.get() will return the target object.

There are other degrees of reference weakness. A soft reference isn’t required to behave any differently to a weak reference, but while memory permits, may retain the object for longer. There are also phantom references which are weaker than weak references, but they’re a little different, you can’t get the target object using a phantom reference and I’m yet to find a use for them which can’t be substituted by just using a finalize() method.

Object‘s wait method causes the Thread the Object is running in to stop executing, possibly forever.

It won’t continue executing until notify() has been called, or unless wait() was called with a timeout parameter in which case it will continue after the timeout period.

The notifyAll() method can be used to notify all Threads waiting on the Object Thread’s monitor.

The finalize method is called by the garbage collector when it has concluded that there are no more strong references (I’ll discuss these and how they differ from other types of references in a later post) to the Object instance. It is only called once and after it has been called the Object may be discarded.

I used to write software used in the UK’s NHS. We used a thick Java client which employed Swing for the GUI. It was multi-threaded, not unit tested, based on legacy software and hadn’t had the level of design detail it sorely needed.

We had to cache lots of information about the examinations available, hospital details, user details, patient details, etc. Large amounts of data would be retrieved from the server and discarded very quickly and from time to time we would run into memory problems.

At the time memory profiling was somewhat in it’s infancy, at least in Java IDEs and I needed a way of establishing if we’d made certain Objects available for garbage collecting. Overriding the finalize method and adding some logging allowed me to quickly establish how many of the Object instances which had been created had all strong references removed and were marked as finalized. This trivial step was a significant help in tracking down problem Objects.

These two methods are at first glance for the same purpose. Equals returns true if the Object passed as the parameter is the same value as the one on which the method is called. HashCode returns an int representation of the Object such that if two Objects are equal they will return the same value.

However, two Objects which are not equal may return the same hashCode.

Ok, so the use of equals() is obvious, but what use does the hashCode() method have?

I’ll take java.util.HashMap as an example. Here we have an Object into which we put key-value pairs. Let’s consider the containsKey() method to see how it works. It could simply have an array of keys an iterate through them, calling equals() on key each. If we’re unlucky though, it could be the last key in a very long array. The implementation it uses is likely to be quicker, thanks in no small part to hashCode().

HashMap stores an array of what are generally termed bins or buckets – these are just positions within the array. Essentially these bins contain a linked list – a group of Entry Objects which store the key, value and next Entry. We can use equals to see if any of the entries have a key that matches ours. The magic though is in finding which bin’s linked list our key is in. The position of the bin is simply the hashCode of the key, modulus the number of bins. If we’ve written our hashCode() implementation well enough the keys will be spaced out evenly amongst the bins.

HashMap has a load factor – it increases the number of bins as Entries are added to the HashMap, this ensures the linked list doesn’t get too large, but also prevents excessive memory usage. It’s worth noting that if we return a hard coded value for the hashCode then all our Objects will end up in the same bin and we’ll just have the performance characteristics inherent with a linked list.

Follow

Get every new post delivered to your Inbox.