views:

144

answers:

3

Why does this code not print an exception stack trace?

public class Playground {

    /**
     * @param args
     */
    public static void main(String[] args) {
        startThread();
    }

    private static void startThread() {
        ScheduledExecutorService timer = Executors
                .newSingleThreadScheduledExecutor();
        Runnable r = new Runnable() {
            int dummyInt = 0;
            boolean dummyBoolean = false;

            @Override
            public void run() {
                dummyInt = Integer.parseInt("AAAA");

                if (dummyBoolean) {
                    dummyBoolean= false;
                } else {
                    dummyBoolean= true;
                }

            }

        };

        timer.scheduleAtFixedRate(r, 0, 100, TimeUnit.MILLISECONDS);

    }

}

How can I get it to?

I would expect to see this:

java.lang.NumberFormatException: For input string: "AAAA"
    at java.lang.NumberFormatException.forInputString(Unknown Source)
    at java.lang.Integer.parseInt(Unknown Source)
    at java.lang.Integer.parseInt(Unknown Source)
    at Playground$1.run(Playground.java:25)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask$Sync.innerRunAndReset(Unknown Source)
    at java.util.concurrent.FutureTask.runAndReset(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPeriodic(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
+7  A: 

The executor probably sets its own uncaught exception handler on the thread, so the stack trace won't be printed to the console. If an exception is thrown in the Runnable you can get it from the ScheduledFuture object returned by the scheduleAtFixedRate method:

ScheduledFuture<?> future = timer.scheduleAtFixedRate(r, 0, 100, TimeUnit.MILLISECONDS);
try {
    future.get();
} catch (ExecutionException e) {
    Throwable cause = e.getCause();
    cause.printStackTrace();
}
Kevin K
There's no need for it to set an uncaught exception handler on the thread. It needs to catch the exception anyway to report it to the future, and can't rethrow the exception because it still needs the thread.
Tom Hawtin - tackline
A: 

There is a similar question that provides an answer Unhandled exceptions with Java scheduled executors here on StackOverflow.

Basically what you can read in the scheduleAtFixedRate() javadoc:

If any execution of the task encounters an exception, subsequent executions are suppressed

So, I'd generalise from here that you never get to see your exceptions when submitting tasks through ScheduledExecutorService.scheduleAtFixedRate().

pajton
+1  A: 

The executor service tends to swallow exceptions for some reason. It can make debugging quite challenging. Just add a try catch around the contents of your run method like this:

public void run() {
  try
    dummyInt = Integer.parseInt("AAAA");

    if (dummyBoolean) {
      dummyBoolean= false;
    } else {
      dummyBoolean= true;
    }
  } catch (Exception e){
    e.printStackTrace();
  }

}

Here's a related question.

Jay Askren