Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ScheduledExecutorService and uncaught Error

A discussion in Code Review chat determined the following behaviour from a ScheduledExecutorService:

A task scheduled to run fails with a 'serious' problem, but there's no report, exception, or log of the problem. In other contexts, the application would normally terminate with an Error. In the context of the ScheduledExecutorService, though, there is no Exception/Error 'handling' at all.

First, to fabricate a problem. The following class has a static initializer that is guaranteed to fail:

public class InitializerFault {
    
    private static final int value = Integer.parseInt("fubar");
    
    @Override
    public String toString() {
        return "" + value;
    }

}

When run as:

public static void main(String[] args) {
    System.out.println(new InitializerFault());
}

it produces (which is exactly what I would expect):

Exception in thread "main" java.lang.ExceptionInInitializerError
    at SimpleHandler.main(SimpleHandler.java:5)
Caused by: java.lang.NumberFormatException: For input string: "fubar"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:580)
    at java.lang.Integer.parseInt(Integer.java:615)
    at InitializerFault.<clinit>(InitializerFault.java:4)
    ... 1 more

But, when run as:

private static final Thread buildThread(Runnable r) {
    Thread t = new Thread(r, "TestThread");
    t.setDaemon(true);
    System.out.println("Built thread " + t);
    return t;
}
public static void main(String[] args) throws InterruptedException {
    // use a thread factory to create daemon threads ... can be non-daemon as well.
    ScheduledExecutorService ses = Executors.newScheduledThreadPool(
           2, (r) -> buildThread(r));
    ses.scheduleAtFixedRate(
           () -> {System.out.println(new InitializerFault());},
           500, 1000, TimeUnit.MILLISECONDS);
    Thread.sleep(3000);
    System.out.println("Exiting");
}

it produces just:

Built thread Thread[TestThread,5,main]
Exiting

There is no mention of any error, no fault, no dump, nothing. This ExceptionInInitializerError has resulted in a complicated real-life debug process, where the problem was very hard to isolate.

Two questions:

  1. is this expected Java behaviour, that Errors in the Executors are 'ignored'?
  2. what's the right way to handle this situation?
like image 854
rolfl Avatar asked Dec 03 '14 13:12

rolfl


1 Answers

ScheduledExecutorService.scheduleAtFixedRate returns a ScheduledFuture. If we call ScheduledFuture.get() the thread will block and wait for the periodic task completion, which may happen upon task cancellation or if the task throws an exception. In the latter case get() will throw java.util.concurrent.ExecutionException with wrapped original exception

like image 118
Evgeniy Dorofeev Avatar answered Oct 22 '22 19:10

Evgeniy Dorofeev