У меня нет никакого способа, чтобы объяснить это одно, но я нашел это явление в чужом коде:SecurityException из кода I/O в параллельном потоке
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()
при получении потока из коллекции, похоже, гарантирует, что все попытки выполнить ввод-вывод вызовут SecurityException
. (Скорее всего, вызов любого метода, который может бросить SecurityException
, будет бросок.)
Я понимаю, что parallel()
означает, что он будет работать в другом потоке, который не может иметь те же привилегии, как и тот, который мы начали с , но я думаю, я думал, что структура позаботится об этом для нас.
Удаление вызовов до parallel()
или parallelStream()
на всем протяжении кода позволяет избежать риска. Вставка AccessController.doPrivileged
также исправляет его, но не кажется мне безопасным, по крайней мере, не во всех ситуациях. Есть ли другой вариант?
Просьба указать трассировку стека исключения, которое вы получаете –
Также добавьте код 'SecurityManager', чтобы мы могли точно воспроизвести вашу проблему. –
Возможно, это связано с параллельными потоками, использующими общий пул соединений fork. Как это работает [если вы предоставляете свой собственный пул] (http://stackoverflow.com/a/22269778/829571)? – assylias