我无法解释这个问题,但在别人的代码中发现了这个现象:
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.util.stream.Stream;
import org.junit.Test;
public class TestDidWeBreakJavaAgain
{
@Test
public void testIoInSerialStream()
{
doTest(false);
}
@Test
public void testIoInParallelStream()
{
doTest(true);
}
private void doTest(boolean parallel)
{
Stream<String> stream = Stream.of("1", "2", "3");
if (parallel)
{
stream = stream.parallel();
}
stream.forEach(name -> {
try
{
Files.createTempFile(name, ".dat");
}
catch (IOException e)
{
throw new UncheckedIOException("Failed to create temp file", e);
}
});
}
}
启用安全管理器后,仅在流上调用parallel()
或在从集合获取流时调用parallelStream()
似乎保证所有尝试执行I/O的操作都会抛出SecurityException
。(最有可能的是,调用任何可能抛出SecurityException
的方法,都将抛出该异常。)
我理解parallel()
意味着它将在另一个线程中运行,该线程可能没有与我们开始时相同的特权,但我认为框架会为我们处理这个问题。
在整个代码库中删除对parallel()
或parallelStream()
的调用可以避免风险。插入AccessController.doPrivileged
也可以解决问题,但在某些情况下并不安全。还有其他选项吗?
SecurityManager
代码,以便我们能够精确地复现您的问题。 - Tagir ValeevThreadLocal
中的上下文,例如Spring的SecurityContext
,请参见例如此问题。 - Andrew Spencer