您知道为什么Java安全管理器不禁止创建新线程或启动它们吗?new FileWriter在安全管理器下,但new Thread()和threadInstance.start()都不在安全管理器下,并且可以被调用。
- 禁止创建和启动线程会有用吗?
- 实现起来难吗?
- 创建和启动新线程并不是禁止的关键吗?
您知道为什么Java安全管理器不禁止创建新线程或启动它们吗?new FileWriter在安全管理器下,但new Thread()和threadInstance.start()都不在安全管理器下,并且可以被调用。
无法定义一项安全策略来防止代码使用标准的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.SecurityManager只有在代码尝试在根ThreadGroup中创建线程时才执行权限检查。同时,SecurityManager的getThreadGroup方法总是返回当前线程的线程组,这永远不会是根线程组,因此总是会被授予创建新线程的权限。
解决方法之一是子类化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")