United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: 6450211 ThreadPoolExecutor.afterExecute sees RuntimeExceptions, but not Errors
6450211 : ThreadPoolExecutor.afterExecute sees RuntimeExceptions, but not Errors

Details
Type:
Bug
Submit Date:
2006-07-19
Status:
Closed
Updated Date:
2011-05-18
Project Name:
JDK
Resolved Date:
2011-05-18
Component:
core-libs
OS:
generic
Sub-Component:
java.util.concurrent
CPU:
generic
Priority:
P3
Resolution:
Fixed
Affected Versions:
6
Fixed Versions:
7

Related Reports
Relates:
Relates:

Sub Tasks

Description
ThreadPoolExecutor.afterExecute takes a Throwable, and is specified to be
passed any RuntimeException or Error thrown by the task.

However the code only handles RuntimeException, causing the results below to 
be different for Error.

------------------
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;

public class Bug6 {
    private static final AtomicInteger uncaughtExceptions
	= new AtomicInteger(0);

    private static final Thread.UncaughtExceptionHandler handler
	= new Thread.UncaughtExceptionHandler() {
		public void uncaughtException(Thread t, Throwable e) {
		    uncaughtExceptions.getAndIncrement(); }};

    static void report(String label, ThreadPoolExecutor tpe) {
	System.out.printf("%10s: active=%d, submitted=%d, completed=%d%n",
			  label,
			  Thread.activeCount() - 1,
			  tpe.getTaskCount(),
			  tpe.getCompletedTaskCount());
    }

    static final Map<Class<?>, Integer> counts
	= new HashMap<Class<?>, Integer>();

    static class MyExecutor extends ThreadPoolExecutor {
	MyExecutor() {
	    super(10, 30, 1L, TimeUnit.HOURS,
		  new LinkedBlockingQueue<Runnable>());
	}

	@Override protected void afterExecute(Runnable r, Throwable t) {
	    if (t != null) {
		Class<?> klazz = t.getClass();
		Integer x = counts.get(klazz);
		counts.put(klazz, x == null ? 1 : x + 1);
	    }
	}
    }

    public static void main(String[] args) throws Throwable {
	Thread.setDefaultUncaughtExceptionHandler(handler);

	final int count = 8;
	final CyclicBarrier barrier = new CyclicBarrier(count + 1);
	ThreadPoolExecutor tpe = new MyExecutor();

	for (int i = 0; i < 5; i++) {
	    tpe.execute(new Runnable() {
		    public void run() {
			throw new RuntimeException();
		    }});
	    tpe.execute(new Runnable() {
		    public void run() {
			throw new Error();
		    }});
	}

	tpe.shutdown();
	tpe.awaitTermination(1L, TimeUnit.HOURS);

	System.out.printf("RuntimeException => %d%n",
			  counts.get(RuntimeException.class));
	System.out.printf("Error => %d%n",
			  counts.get(Error.class));
    }
}
------------------
$ jver 6 jr Bug6
==> javac -source 1.6 -Xlint:all Bug6.java
==> java -esa -ea Bug6
RuntimeException => 5
Error => null

                                    

Comments
EVALUATION

Submitter is correct.
                                     
2006-07-19



Hardware and Software, Engineered to Work Together