Java


IntelliJ is an awesome IDE from JetBrains. jconsole is a powerful tool for examining the state of an executing JVM. When you’re debugging JVM code in IntelliJ, you might find that jconsole can’t connect to your JVM while you’re sitting on a breakpoint. This is because the default breakpoint behavior in IntelliJ is to stop the whole VM, not just the thread that’s sitting on the breakpoint. If you try to connect jconsole to the JVM in this state, it will time out.

This is easy to fix:
1. Right click on your breakpoint and choose “Properties”
2. Change the suspend policy from “All” to “Thread”

“…and you’re done kid.” Imagine I said that in a Boston accent.

You can now connect to the JVM while sitting on that breakpoint. Problem solved.

Help! My Java application keeps crashing! OutOfMemoryError?! My hair is on fire! Please don’t let the invisible fire burn my friend!!!

1. Increase max heap size

Some applications are complex and large enough that they simply need more memory.
Try increasing the max heap size when you start the JVM by adding the flag -Xmx. So your start-up will look something like this: java -Xmx1024m MyApp (which is equivalent to java -Xmx1g MyApp)

The downside to this is that your application will suffer from longer garbage collection cycles, it may be better to fix the greedy code.

But what if your application still runs out of memory? Seems like you have a leak.

2. Detect memory leak

Learn to use a tools like jmap and Thread Dump Analyser (TDA). Run jmap -histo
(where pid is the process-id of your Java application) a few times and compare the output. Read my earlier blog posts on fun with heap dump analysis.

3. Carefully read your code

There are many ways to leak memory in Java code. Watch out for thread local variables — especially in a thread pool. Each thread stores its own state so anything you put on there will last the lifetime of the thread. If your threads are recycled through a thread pool that state may hang around for a long time.

Mutable static collections are bad. Static fields are retained by the class and therefore its classloader. That means your collection will hang around for the lifetime of that class. Come to think of it, it is better not to use mutable statics.

If you re-implement the hashcode and equals methods and get it wrong you’ll shoot yourself in the foot. Here is why: when you store an object in a HashMap the collection will call your (wrong) hashcode method to determine that object’s position. On look-up, the map uses the (wrong) hashcode method again and then calls (wrong) equals method to check it retrieved the correct object. If you break the implementations of these two methods you can add objects into the HashMap but can’t get them back. Worse, you can add the same thing repeatedly and it will not overwrite the old value because hashcode keeps returning different values for the same object.

4. Circuit breakers

If you do have to compute over potentially large collections of objects then use weak references as circuit breakers. I wrote a series of blog posts that will serve as a good primer for weak references. In particular: JVM Memory Primer, Java References and Reachability Explained.

Monitoring JVM memory usage and tweaking system options is something we do all the time. Once you’ve fixed your leaks you need to continue to monitor systems and run load tests to project usage into the future. Be proactive; don’t wait for an OutOfMemoryError to remind you.

After my previous post on references one of the team asked me for an example use for phantom references. The best I could recall was to keep track of an object and perform some postmortem clean upon its destruction. Very important for database connections and caches.

But can’t you do that with the finalize method?

Well no, not with any guarantees. Here’s why:

Firstly, we don’t know when the garbage collector will run. It is non-deterministic. In fact, if your program doesn’t use up its allocated memory it doesn’t ever need to GC — no objects would befinalized. Secondly, any objects that are strongly referenced when the runtime quits will not be GC’d. Their finalizer code will never be called.

Object finalization happens after an object has been marked as garbage but before memory has been reclaimed. You can screw around with this by creating a strong reference to a garbage object during its finalization:

myObject = this;

If you do this (please don’t!) the object comes back to life because it is strongly reachable via myObject. However, the object you have a reference to will never have its finalizer code called again. That’s bad. Phantom references don’t allow this:

“In order to ensure that a reclaimable object remains so, the referent of a phantom reference may not be retrieved: The get method of a phantom reference always returns null.”
[PhantomReference API]

Recall that the constructor for a PhantomReference takes a ReferenceQueue. Phantom references are enqueued once the object has been finalized and the memory has been reclaimed. If you process this queue in your own cleanup thread then you are guaranteed that the referents are gone.

Unlike soft and weak references, phantom references are not automatically cleared by the garbage collector as they are enqueued
[PhantomReference API] – So you just remember to clean up and dequeue.

If that’s not enough to convince you that finalizers are troublesome then maybe an optimization argument will help: the runtime’s finalizer thread is responsible for calling the finalize method on garbage objects. This can slow up your application during GC cycles. Especially if your finalizer code does a synchronous wait for some external process (like a database confirming the connection was closed). Taking control of cleanup with your own thread(s) by processing a reference queue is likely to be way more efficient.

Finalizerly, if the garbage collector never runs then unreachable objects are not identified which means phantom references will not be put into the reference queue. That’s important to remember too.

As a follow up to my last post on Java references I wanted to blog a clear explanation on reachability. But there is no way I can be more succinct than the Java API docs. So I’m going to invoke “fair use” and reference the source.

– begin quote –

Going from strongest to weakest, the different levels of reachability reflect the life cycle of an object. They are operationally defined as follows:

  • An object is strongly reachable if it can be reached by some thread without traversing any reference objects. A newly-created object is strongly reachable by the thread that created it.
  • An object is softly reachable if it is not strongly reachable but can be reached by traversing a soft reference.
  • An object is weakly reachable if it is neither strongly nor softly reachable but can be reached by traversing a weak reference. When the weak references to a weakly-reachable object are cleared, the object becomes eligible for finalization.
  • An object is phantom reachable if it is neither strongly, softly, nor weakly reachable, it has been finalized, and some phantom reference refers to it.
  • Finally, an object is unreachable, and therefore eligible for reclamation, when it is not reachable in any of the above ways.

– end quote –

I’m on a memory management kick. Understanding how the Java runtime partitions memory, allocates space for objects, moves objects around, and performs garbage collection (see previous post) is a good base for our quest to writing memory conscious code. In this blog post I’ll describe Java’s four reference types, which you can use to assist the JVM in its memory management duties.

In order from strongest to weakest these references are: Strong, Soft, Weak, Phantom.

Strong References

These are your regular object references:

Server server = new Server();

The variable server holds a strong reference to a Server object. OK, before you stop reading there is a point to this: objects that are reachable through any chain of strong references are not eligible for garbage collection. Usually this is what you want. But not always.

Imagine for a minute that you’re coding an Enterprise Web App backed by a large Oracle database. When users navigate your web app it loads data into memory from Oracle. Sometimes the same data is regularly accessed so you decide to cache it in a Map. By storing strong references you’ve just introduced a memory leak. “Ha!”, you say, “then I’ll write a memory manager that throws out least frequently used objects when we begin to run out of memory”. But doesn’t the JVM already manage memory for you?

Weak References

A weak reference will not pin an object into memory. An object that is identified as only weakly reachable will be collected at the next GC cycle.

WeakReference<Cacheable> weakData = new WeakReference<Cacheable>(data);

To access data call weakData.get(). This call to get may return null if the weak reference was garbage collected: you must check the returned value to avoid NPEs.

Java contains collections that use weak references. For example, the WeakHashMap class stores keys (not values) as weak references. If the key is GC’d then the value will automatically be removed from the map too.

Since weak references are objects too we need a way to clean them up (they’re no longer useful when the object they were referencing has been GC’d). If you pass a ReferenceQueue into the constructor for a weak reference then the garbage collector will append that weak reference to the ReferenceQueue when it is no longer needed. You can periodically process this queue and deal with dead references.

Soft References

A SoftReference is like a weak reference but it is less likely to be garbage collected. Soft references are cleared at the discretion of the garbage collector in response to memory demand. The virtual machine guarantees that all soft references to softly-reachable objects will have been cleared before it would ever throw an OutOfMemoryError.

Phantom References

In practice these are rarely used.

Key point: phantom references are the most tenuous of all reference types: calling get will always return null.

So how are they useful? When you construct a phantom reference you must always pass in a ReferenceQueue. This indicates that you can use a phantom reference to see when your object is GC’d. The phantom reference is enqueued after it has been physically removed from memory — as opposed to weak references which are enqueued before they’re finalized or GC’d.

Hey, so if weak references are enqueued when they’re considered finalizable but not yet GC’d we could create a new strong reference to the object in the finalizer block and prevent the object being GC’d. Yep, you can but you probably shouldn’t do this. To check for this case the GC cycle will happen at least twice for each object, unless that object is reachable only by a phantom reference. This is why you can run out of heap even when it your memory contains plenty of garbage. Phantom references can prevent this.