java - 为什么 java 安全管理器既不禁止创建 new Thread() 也不禁止启动它?

标签 java multithreading securitymanager

您知道为什么 Java 安全管理器不禁止创建或启动新线程的解释吗? new FileWriter 在安全管理器下,但 new Thread() 和 threadInstance.start() 都不是在安全管理器下,可以调用。

  1. 禁止它不是很有用吗?
  2. 会不会很难实现?
  3. 或者创建和启动新线程与禁止它无关紧要?

最佳答案

无法定义安全策略来阻止代码使用标准 Java SecurityManager 创建和启动新线程。

假设您有以下代码:

public class Test {
  public static void main(String [] args) {
    System.out.println(System.getSecurityManager() != null ? "Secure" : "");
    Thread thread = new Thread(
      new Runnable() { 
        public void run() {
          System.out.println("Ran");
        }
    });
    thread.start();
  }
}

然后使用以下命令运行它:

java -Djava.security.manager -Djava.security.policy==/dev/null Test

它将运行得很好并输出:

Secure
Ran

即使我们将安全策略设置为/dev/null,这将授予对任何代码的零权限。因此,不可能授予更少的权限来阻止代码创建该线程。

这是因为标准 java.lang.SecuritManager 仅在代码尝试在根线程组中创建线程时执行权限检查。同时,SecurityManager 的 getThreadGroup 方法总是返回当前 Thread 的线程组,它永远不会是根线程组,所以创建新 Thread 的权限总是被授予。

解决这个问题的一种方法是继承 java.lang.SecurityManager 并覆盖 getThreadGroup 方法以返回根 ThreadGroup。这将允许您根据代码是否具有 java.lang.RuntimePermission“modifyThreadGroup”来控制代码是否可以创建线程。

所以如果我们现在定义一个 SecurityManager 的子类如下:

public class ThreadSecurityManager extends SecurityManager { 
  
  private static ThreadGroup rootGroup;
  
  @Override
  public ThreadGroup getThreadGroup() {
    if (rootGroup == null) {
      rootGroup = getRootGroup();
    }
    return rootGroup;
  }

  private static ThreadGroup getRootGroup() {
    ThreadGroup root =  Thread.currentThread().getThreadGroup();
    while (root.getParent() != null) {
     root = root.getParent();
    }
    return root;
  }
}

然后再次运行我们的命令,但这次指定我们的子类 ThreadSecurityManager:

java -Djava.security.manager=ThreadSecurityManager -Djava.security.policy==/dev/null Test

当我们尝试创建新线程时,我们的测试类出现异常:

Exception in thread "main" java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "modifyThreadGroup")

关于java - 为什么 java 安全管理器既不禁止创建 new Thread() 也不禁止启动它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15868534/

相关文章:

java - 尽可能将变量定义为 "locally"是否会使实现更快?

Android线程无法访问Main.xml

java - java.lang.SecurityManager 中的初始化字段有什么用?

Java : Is there an API to find which class needs the permission in a Custom security manager class?

java - 将文本设置为 fragment 中的 TextView

java - 我可以在没有 ORM 的情况下将 XML 导入 Postgres 数据库吗?

ios - 如何计算 iOS 中的事件线程数

Java:线程等待对象时是否释放所有监视器?

java - 异常: access denied ("java.net.SocketPermission" "localhost:80" "listen,resolve")

Java日期格式转换 - 月份错误