--- jsr166/src/jdk8/java/util/concurrent/ThreadPoolExecutor.java 2017/06/04 23:04:03 1.2 +++ jsr166/src/jdk8/java/util/concurrent/ThreadPoolExecutor.java 2017/07/24 15:09:05 1.3 @@ -6,6 +6,9 @@ package java.util.concurrent; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.ConcurrentModificationException; import java.util.HashSet; @@ -544,6 +547,9 @@ public class ThreadPoolExecutor extends private static final RuntimePermission shutdownPerm = new RuntimePermission("modifyThread"); + /** The context to be used when executing the finalizer, or null. */ + private final AccessControlContext acc; + /** * Class Worker mainly maintains interrupt control state for * threads running tasks, along with other minor bookkeeping. @@ -1279,6 +1285,9 @@ public class ThreadPoolExecutor extends throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); + this.acc = (System.getSecurityManager() == null) + ? null + : AccessController.getContext(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; @@ -1448,9 +1457,18 @@ public class ThreadPoolExecutor extends /** * Invokes {@code shutdown} when this executor is no longer * referenced and it has no threads. + * + *

This method is invoked with privileges that are restricted by + * the security context of the caller that invokes the constructor. */ protected void finalize() { - shutdown(); + SecurityManager sm = System.getSecurityManager(); + if (sm == null || acc == null) { + shutdown(); + } else { + PrivilegedAction pa = () -> { shutdown(); return null; }; + AccessController.doPrivileged(pa, acc); + } } /**