为什么java安全管理器既不禁止创建新的Thread()也不禁止它?

bas*_*iat 11 java multithreading securitymanager

你碰巧知道解释为什么java安全管理器不禁止创建新线程或启动它们吗?新的FileWriter在安全管理器下,但新的Thread()和threadInstance.start()都不是更安全的安全管理器,并且可以调用.

  1. 禁止它会不会有用吗?
  2. 难以实施吗?
  3. 或者创建和启动新线程并不是那么禁止它?

alp*_*oop 14

接受的答案是错误的:无法定义一个安全策略来阻止代码使用标准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();
  }
}
Run Code Online (Sandbox Code Playgroud)

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

java -Djava.security.manager -Djava.security.policy==/dev/null Test
Run Code Online (Sandbox Code Playgroud)

它会运行得很好并输出:

Secure
Ran
Run Code Online (Sandbox Code Playgroud)

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

这是因为标准java.lang.SecuritManager仅在代码尝试在根ThreadGroup中创建线程时才执行权限检查.同时,SecurityManager的getThreadGroup方法总是返回当前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;
  }
}
Run Code Online (Sandbox Code Playgroud)

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

java -Djava.security.manager=ThreadSecurityManager -Djava.security.policy==/dev/null Test
Run Code Online (Sandbox Code Playgroud)

当我们尝试创建新线程时,我们在Test类中遇到异常:

Exception in thread "main" java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "modifyThreadGroup")
Run Code Online (Sandbox Code Playgroud)