Mot
Mot

Reputation: 29530

SwingUtilities.invokeAndWait does not wait?

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?

Upvotes: 2

Views: 694

Answers (3)

Richard
Richard

Reputation: 56

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.

Upvotes: 3

Ana B
Ana B

Reputation: 11

I sometimes get NullPonterExeption.... weird

java version "1.6.0_31" Java(TM) SE Runtime Environment (build 1.6.0_31-b04-415-11M3635) Java HotSpot(TM) Client VM (build 20.6-b01-415, mixed mode)

Upvotes: 1

Marko Topolnik
Marko Topolnik

Reputation: 200148

My SSCCE:

public abstract class FunctionRunnable<V> implements Runnable {
  private V result;
  private Throwable thr;

  protected abstract V calculate();

  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;
  }

  public static void main(String[] args) throws Exception {
    final FunctionRunnable<Boolean> runnable = new FunctionRunnable<Boolean>() {
      public Boolean calculate() { return doCalculation(); }
      private boolean doCalculation() {
        try { Thread.sleep(2000); } catch (InterruptedException e) {}
        return false;
      }};
    SwingUtilities.invokeAndWait(runnable);
    System.out.println(runnable.getResult().booleanValue());
  }
}

My Java version:

$java -version
java version "1.6.0_31"
Java(TM) SE Runtime Environment (build 1.6.0_31-b04-415-11M3635)
Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01-415, mixed mode)

Started, ran for 2 seconds, printed false.

Upvotes: 3

Related Questions