gpt4 book ai didi

java - AccessControlException 并不总是在公共(public) Java 池的线程中引发

转载 作者:行者123 更新时间:2023-12-01 09:20:36 27 4
gpt4 key购买 nike

我有以下程序:

       public static void main(String[] args) throws Exception{

ForkJoinTask<?> read = ForkJoinPool.commonPool().submit(new Runnable() {
@Override
public void run() {
SecurityManager appsm = System.getSecurityManager();

if (appsm != null) {
appsm.checkPermission(new PropertyPermission("os.arch", "read"));
System.out.println("Permissions are OK!!!!");
} else {
System.out.println("No system mangerrr :(");
}
}
});


read.get();

System.out.println("End of the program!");
}
我还设置了这个系统属性: -Djava.security.manager我的问题如下 - 为什么有时我会得到“程序结束!”写入标准输出,但有时我得到 Exception in thread "main" java.util.concurrent.ExecutionException: java.security.AccessControlException: access denied ("java.util.PropertyPermission" "os.arch" "read") ?
由于公共(public)池的线程是在没有任何权限的情况下创建的,它不应该总是抛出这个异常吗?这种行为不应该总是相同的,并且在不同的执行过程中不应该改变吗?
我使用 Zulu OPEN JDK 8.0.252 从我的 IntelliJ IDE 运行它。

最佳答案

发生这种情况是因为任务提交到 ForkJoinPool可以在 join 上的调用线程中执行.在您的情况下,当您调用 read.get() 时会发生这种情况;大多数时候,来自公共(public)池的工作人员会拿起任务并执行它(安全检查失败),但有时任务在调用线程中运行(并且安全检查通过)。
您可以通过记录线程名称来确认这一点。

public void run() {
SecurityManager appsm = System.getSecurityManager();
if (appsm != null) {
System.err.println("Thread: " + Thread.currentThread().getName());
appsm.checkPermission(new PropertyPermission("os.arch", "read"));
System.out.println("Permissions are OK!!!!");
} else {
System.out.println("No system mangerrr :(");
}
}
这将记录 Thread: ForkJoinPool.commonPool-worker-1当安全检查失败和 Thread: main当安检通过时。
出现这两种情况的行为差异是因为您的主线程有 os.arch read权限,但您的公共(public)池中的线程没有权限。
来自 ForkJoinPool文档:

The common pool is by default constructed with default parameters, but these may be controlled by setting three system properties:

  • java.util.concurrent.ForkJoinPool.common.parallelism - the parallelism level, a non-negative integer
  • java.util.concurrent.ForkJoinPool.common.threadFactory - the class name of a ForkJoinPool.ForkJoinWorkerThreadFactory
  • java.util.concurrent.ForkJoinPool.common.exceptionHandler - the class name of a Thread.UncaughtExceptionHandler

If a SecurityManager is present and no factory is specified, then the default pool uses a factory supplying threads that have no Permissions enabled.


公共(public)池中的默认安全性非常保守。它使用 运行任务没有特权和清理 ThreadLocal任务完成后vars,防止信息泄露。
公共(public)池安全性必须保守,因为它适用于所有代码——如果它默认在主 SecurityManager 下运行。那么您尝试进一步沙箱化的任何代码都可以通过在公共(public)池中运行任务来提升权限。
如果您不想让代码以 SecurityManager 所允许的权限运行公共(public)池中的任务您已经在命令行上配置了,那么您必须设置 java.util.concurrent.ForkJoinPool.common.threadFactory到您提供的实现,例如
public final class CustomForkJoinWorkerThreadFactory implements ForkJoinPool.ForkJoinWorkerThreadFactory {
@Override
public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
return ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool);
}
}

关于java - AccessControlException 并不总是在公共(public) Java 池的线程中引发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62663207/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com