Similar Ideas

Tags

A troubleshooter's view on the IBM JDK vs "the other guys"

I'll preface this post with two facts: 1. I'm an IBMer and I am not impartial to WebSphere and IBM Javatm, and 2. my primary job function involves solving (sometimes extraordinary) customer problems. That aside, what I wanted to discuss in this post is a comparison between the serviceability capabilities of the IBM JDK and what we'll call: "the other guys". "The other guys" will suffice for a description of any non-IBM Java SDK for the purposes of this post.

This post will not be an all inclusive resource for the differences between the two JDK implementations. What I want to cover are some of the strengths of the IBM JDK over "the other guys" and why you should care. So let's get on with it:

Java dumpsTypically produced with a “kill -3” or compatible command, the Java dump (also known as a thread dump or java core) contains a snapshot of the JVM state at the time it was taken. First and foremost the Java dump contains a listing of all the Java threads in the JVM. If you are using one of "the other guys" JVMs, that is about where the usefulness of the Java dump stops. You have basic thread status like the runtime state of the thread (Runnable, Condition Wait, Monitor Wait) and some Java monitor information (object locking) but that's it. Additionally, the dump is written to the native standard out of the JVM along with any verbose garbage collection data output you may have enabled. Obviously, it would be helpful to know when the Java dump was trigger wouldn't it? Too bad. "The other guys" don't do this. However, the IBM JDK does! Additionally, with the IBM JDK, you get a great deal more data from your Java dump. Here's a breakdown:

time stamp of the Java dump

signal that produced the Java dump

which library the signal was raised in (SIGSEV)

the currently executing thread at the time of the dumpo

a summary of the operating system environment

the ulimits in effect for the JVM

the environment variables in effect for the JVM shell

the libraries loaded by the JVM

the full JVM command line

last cycles of garbage collections prior to the dump

state of the internal JVM memory segments

the names of all the loaded classes and the classloader that loaded it

I think you can see here that the serviceability that the IBM JDK provides far outweighs that of "the other guys". But let's not stop with Java dumps, next topic...

Verbose garbage collection loggingNo doubt that "the other guys" JVMs probably sport the most garbage collection parameters in the world, however, they have one fatal flaw in serviceability in my eyes. A lack of non-relative time stamps for each garbage collection cycle. Using "the other guys" JDK, once you actually tell it you want it to output timestamps for each cycle (why this isn't the default astounds me to no end) you don't actually get a real human readable time stamps. No, you get a “timestamp” that tells you how many seconds have passed since the start of the JVM. Does it tell you in the log when the JDK started? No. Then is this timestamp value really useful? Again, no.

The IBM JDK handles this in a much more user-friendly way. For each garbage collection cycle you get a real time stamp value like this:

Having this actual time stamp value allows you to easily correlate the garbage collection activity to other system logs allowing you to determine how your JVM was performing at an exact point in time. I can't tell you how many times I've been faced with a customer trying to correlate poor JVM performance with a spike in response times from their load generator tool only to have to guess exactly when the garbage collection cycles actual ran because they were using one of "the other guys" JDKs! It's maddening and in most cases you have to result to something like a cron job that echos the outpout of the “date” command into the verbose garbage collection log just so you can get an approximation of times. Again, a huge failure on the part of "the other guys" JDKs in terms of serviceability in my opinion.

So, we're at two strikes now, right? Right. So on to strike three...

Object allocation sizeAt some point in your experience with Java you're going to run across a situation where you are seeing poor garbage collection performance or the JVM will throw an OutOfMemoryError. There are too many reasons for these issues but inevitably you're going to run across a situation where you suspect that some application code is allocating some rather large Java objects to the heap. If you're using the IBM JDK you have output in the verbose garbage collection logs that tells you exactly how much memory was being requested when an allocation failure cycle was started. For example:

In the example above, the allocation failure was triggered by some Java code requiring an object of 24 bytes in size. If you were using one of "the other guys" JDKs, you would have zero insight into the allocation sizes. None, nada, zip, nil. As far as I know, there is no way to get this information easily, furthermore, the IBM JDK has command line parameters that allow you set a allocation size threshold where, if exceeded, a Java stack trace is printed allowing you to see what code asked for the object that broke the threshold size limit. No such love from "the other guys". And again, as far as I know there is no way to get this data from the JVM by any means (including custom JVMTI, JVMPI, or JVMMI agents/interfaces).

Hopefully, I've been able to show no less than three really good reasons for you to consider using the IBM JDK over "the other guys". When it comes to serviceability it's pretty clear (at least to me) that the IBM JDK handily beats "the other guys" JDK in most, if not all, aspects. But don't just take my word on it, download a copy of the IBM JDK and check it out for yourself!