Following code worked fine
abstract class FunctionRunnable<V> implements Runnable {
protected abstract V calculate();
private V result;
private Throwable thr;
public synchronized final void run() {
try {
result = calculate();
}
catch (Throwable thr) {
this.thr = thr;
}
}
public synchronized final V getResult() {
if (thr != null) {
throw new RuntimeException(thr);
}
return result;
}
}
...
final FunctionRunnable<Boolean> runnable = new FunctionRunnable<Boolean>() {
public Boolean calculate() {
return doCalculation();
}
private boolean doCalculation() {
...
}
});
SwingUtilities.invokeAndWait(runnable);
final Boolean resultObj = runnable.getResult();
final boolean result = resultObj.booleanValue();
until Apple released 1.6.0_31 for which users of our application sometimes are getting an NPE in the last line.
Do you see a bug in the code or do other people have found similar problems with this particular Java update?
If you look in to the implementation of EventQueue.invokeAndWait you will see that it does not correctly handle spurious wakeup. It calls lock.wait() then does not check whether the runnable has actually finished executing – this means invokeAndWait can return before your runnable has finished executing!
For some reason, spurious wakeup has started happening with reasonable frequency in update 31 on mac os, exposing this long standing bug in EventQueue. I’m not sure what has changed, it doesn’t happen in any other versions of Java.
We fixed this by implementing our own invokeAndWait method with a simple boolean check for completion of the runnable.