I have no way to explain this one, but I found this phenomenon in somebody else's code:
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);
}
});
}
}
When run with the security manager enabled, merely calling parallel()
on a stream, or parallelStream()
when getting the stream from a collection, seems to guarantee that all attempts to perform I/O will throw SecurityException
. (Most likely, calling any method which can throw SecurityException
, will throw.)
I understand that parallel()
means that it will be running in another thread which might not have the same privileges as the one we started with, but I guess I thought that the framework would take care of that for us.
Removing calls to parallel()
or parallelStream()
throughout the codebase avoids the risk. Inserting an AccessController.doPrivileged
also fixes it, but doesn't sound safe to me, at least not in all situations. Is there any other option?