为什么我不能在安全管理器下关闭我自己的执行器服务?
在默认的安全管理器下,如果我创建一个执行器服务(在本例中为 ThreadPoolExecutor),我无法关闭它,只是调用,因此立即死亡:shutdown()
checkPermission("modifyThread")
import java.util.concurrent.*;
class A {
public static void main( String[] args) {
Thread ct = Thread.currentThread();
System.out.println("current thread: " + ct);
ct.checkAccess(); // we have access to our own thread...
ThreadPoolExecutor tpe = new ThreadPoolExecutor(
1, // one core thread
1, // doesn't matter because queue is unbounded
0, TimeUnit.SECONDS, // doesn't matter in this case
new LinkedBlockingQueue<Runnable>(), /* unbound queue for
* our single thread */
new ThreadFactory() {
public Thread newThread(Runnable r) {
// obviously never gets called as we don't add any work
System.out.println("making thread");
return new Thread(r);
}
}
);
tpe.shutdown(); // raises security exception
}
}
孙杰德克:
$ java -Djava.security.manager 当前线程: Thread[main,5,main] 线程 “main” java.security.AccessControlException: access denied (java.lang.RuntimePermission modifyThread) at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323) at java.security.AccessController.checkPermission(AccessController.java:546) at java.lang.SecurityManager.checkPermission(SecurityManager.java:532) atjava.util.concurrent.ThreadPoolExecutor.shutdown(ThreadPoolExecutor.java:1094) at A.main(A.java:22)
OpenJDK:
$ java -Djava.security.manager 当前线程: Thread[main,5,main] 异常线程 “main” java.security.AccessControlException: access denied (java.lang.RuntimePermission modifyThread) at java.security.AccessControlContext.checkPermission(AccessControlContext.java:342) at java.security.AccessController.checkPermission(AccessController.java:553) at java.lang.SecurityManager.checkPermission(SecurityManager.java:549) at java.util.concurrent.ThreadPoolExecutor.checkShutdownAccess(ThreadPoolExecutor.java:711) at java.util.concurrent.ThreadPoolExecutor.shutdown(ThreadPoolExecutor.java:1351) at A.main(A.java:22)
为什么???????创建只有您自己控制的线程池并将其关闭会有什么安全隐患?这是实现中的错误,还是我遗漏了什么?
让我们看看ExperfectorService.shutdown的规范是怎么说的...
启动有序关机,其中将执行以前提交的任务,但不接受任何新任务。如果已经关闭,则调用不会产生其他影响。
Throws:SecurityException - 如果存在安全管理器并关闭此 ExecutorService 可能会操作不允许调用方修改的线程,因为它不持有 RuntimePermission(“modifyThread”),或者安全管理器的 checkAccess 方法拒绝访问。
这。。。几乎是模糊的。该规范没有提到在ExecutorService的生命周期中正在创建的任何“系统线程”,此外,它允许您提供自己的线程,这证明当您这样做时不应该涉及“系统线程”。(如上文在我的样本源中所做的那样)
感觉就像Java SE实现者看到可以提高,所以他们就像,“哦,好吧,我只是在这里添加一个随机的安全检查以确保合规性”......shutdown
SecurityException
问题是,阅读OpenJDK源代码(openjdk-6-src-b20-21_jun_2010),事实证明,创建任何线程的唯一方法是调用您提供的ThreadFactory(在我的测试用例中从未调用过它,因为我不创建任何工作,我不调用prestartCoreThread或preStartAllCoreThreads。).因此,在OpenJDK的ThreadPoolExecutor中,安全检查是无缘无故地完成的(就像在sun-jdk-1.6中所做的那样,但我没有源代码):
/**
* Initiates an orderly shutdown in which previously submitted
* tasks are executed, but no new tasks will be accepted.
* Invocation has no additional effect if already shut down.
*
* @throws SecurityException {@inheritDoc}
*/
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(SHUTDOWN);
interruptIdleWorkers();
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
mainLock.unlock();
}
tryTerminate();
}
checkShutdownAccess
在执行任何操作之前调用...
/**
* If there is a security manager, makes sure caller has
* permission to shut down threads in general (see shutdownPerm).
* If this passes, additionally makes sure the caller is allowed
* to interrupt each worker thread. This might not be true even if
* first check passed, if the SecurityManager treats some threads
* specially.
*/
private void checkShutdownAccess() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(shutdownPerm);
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers)
security.checkAccess(w.thread);
} finally {
mainLock.unlock();
}
}
}
如您所见,它无条件地在安全管理器上调用....关机项目被定义为...私有静态最终运行时权限关闭Perm = new RuntimePermission(“modifyThread”);checkPermission(shutdownPerm)
...据我所知,这完全没有意义,因为这意味着访问系统线程,并且这里没有系统线程在起作用,实际上,根本没有线程,因为我没有提交任何工作或预启动,即使有线程,它们也会是我的线程,因为我传入了.该规范没有说任何关于神奇死亡的内容,除了如果涉及系统线程(它们不涉及),则可能存在.modifyThread
ThreadFactory
SecurityException
基本上,为什么我不能删除检查系统线程访问的行?我认为没有安全隐患需要这样做。其他人怎么没有遇到这个问题???我在问题跟踪器上看到过一个帖子,他们通过将呼叫更改为“解决了”此问题,显然,这并没有为他们解决问题。shutdownNow
shutdown