Abstract: Java deadlocks can be tricky to discover. In this very first Java Specialists' Newsletter, we look at how to diagnose such an error and some techniques for solving it.
Welcome to The Java(tm) Specialists' Newsletter, a low-volume newsletter exploring
experiences of using Java "in the field" (not only
java.lang.reflect.Field
, but that also). The reason I have sent this email to
you is because you were either on a Java course presented by me, or you are a
colleague, or I thought the topic might simply interest you.
Just to clear things up, as I always tell my students, my company's name is Maximum Solutions and our logo is The Java(tm) Specialists' Newsletter, hence the title for the newsletter. This does not mean we are good at Java, it simply means that this is all we do (at the moment). Perhaps in future I will change my logo to "The XML Specialists", or, heaven forbid "The VB Specialists", but then I would have to be really hard-up ;-) The logo is therefore not a display of my arrogance (those of you who know me better would assure you that arrogance is definitely not one of my characteristics, neither is a bad haircut nor rolled up jeans) but is supposed to give me focus in the IT industry.
A warning I feel I have to give you is that the tricks I have discovered in Java are not always "kosher" and are used solely at your own risk. Whenever I mention something that is non-kosher I will also attach a warning label so the more experienced of you can use it and the rest not. Always make sure that your unit tests run before and after a change to a new JDK version, the days of JDK 1.1.x were extremely interesting because each version screwed up the South Africa Locale in a different way. For the past 3.5 years I've been programming exclusively in Java and I can say that it is a fascinating language. Once you dig below the surface of Java it becomes increasingly more fun and interesting to work with, and you end up wanting to exploit the limits of the JDK (last week I made a piece of code I had written with someone else 2 years ago 1000x faster). The JDK 1.3.0 source code contained in the src.jar file when you install the JDK contains a lot of Java code, 574253 lines of Java code to be exact, which is slightly less than the Java program written in Stellenbosch in South Africa where I gained most of my Java programming experience.
javaspecialists.teachable.com: Please visit our new self-study course catalog to see how you can upskill your Java knowledge.
While travelling overseas I had the priviledge of spending some time helping a Java program in dire straits. It was a graphical interface that was supposed to emulate a C++ program running on a server, bla bla bla. Anyway, this application would occasionaly have a thread deadlock with the result that the screen would stop refreshing. Imagine the despair when facing an unfamiliar source base of several 10'000 lines of Java code with a deadlock SOMEWHERE in there?!? The code was well written, but even though, the task was scary. Luckily I had heard somewhere about the secret CTRL+BREAK trick that SUN smuggled into the JDK without telling anybody. If you press CTRL+BREAK while your Java program is running in a command prompt you get a stack trace of exactly what each thread is doing and by looking at the code you easily find which thread is waiting for which lock!
When you get a deadlock in your program you want to be able to reproduce it reliably as quickly as possible, so we got half the team to just concentrate on finding deadlocks that they could reproduce. In the meantime, the other half would look at the stack traces and figure out why the code was deadlocking. In the process of looking we discovered something which I had heard about second-hand but had not encountered myself. Last week I heard of the same problem occuring at another company which took a lot of effort to clear up, so if your program has any GUI in it, especially Swing, it might pay to listen to this:
In Swing, all GUI components have to be changed from within the Swing thread.
This means that you cannot execute jLabel1.setText("blabla")
from within any thread besides the Swing thread.
If you have change any GUI from another thread you should rather say:
SwingUtilities.invokeLater(new Runnable() { public void run() { jLabel1.setText("blabla"); } }
This will do the change that you requested as soon as it can, which is usually within a few microseconds. There is another call invokeAndWait which I have hardly ever used except in race-conditions.
I was under the impression that failure to use invokeLater
would cause some refresh problems of a kind where some parts of
the screen get refreshed and others not, I did not realise it
could cause a thread deadlock (or maybe that is what everyone
was talking about - refresh problem - hmpf - more like a system
meltdown). Luckily you don't always have to call invokeLater
whenever you change a GUI component because in some cases you
already are in the Swing GUI thread, for example if a button is
pressed then the ActionListener.actionPerformed
method will be
called from the Swing thread. However, if you provide a callback
class to another class that is not part of the AWT/Swing group
you will never know what thread it is coming from, so it is
safest to invokeLater.
Remember that any work you do in invokeLater is going to hold up the Swing thread from repainting the window, so please don't do big database queries inside invokeLater but rather only call invokeLater for the parts of the code that are genuinely graphics related. It might pay off to bunch all the GUI related lines in your method by refactoring your code a bit. For information on refactoring look at the book with that title by Martin Fowler.
---
Warning Advanced:
A small optimisation is to have a class that
figures out if the current thread is the Swing thread
(SwingUtilities.isEventDispatchThread()
) and if it is not calls
SwingUtilities.invokeLater(Runnable)
, otherwise it calls the
runnable code directly. This way you can finish everything you
need to do without interference by other threads. Reason for
the Non-Kosher label is that it seems you can have several event
dispatch threads, I don't know under what circumstances so if
you know, please enlighten me. However, it almost seems like
only one of them can be active at any one time.
---
This is the end of my first newsletter, I appreciate any feedback!
Kind regards
Heinz
We are always happy to receive comments from our readers. Feel free to send me a comment via email or discuss the newsletter in our JavaSpecialists Slack Channel (Get an invite here)
We deliver relevant courses, by top Java developers to produce more resourceful and efficient programmers within their organisations.