提交 3563fdc3 编写于 作者: I igerasim

8020669: (fs) Files.readAllBytes() does not read any data when Files.size() is 0

Reviewed-by: alanb, chegar, martin, rriggs
上级 bf632342
......@@ -25,10 +25,10 @@
package java.nio.file;
import java.nio.ByteBuffer;
import java.nio.file.attribute.*;
import java.nio.file.spi.FileSystemProvider;
import java.nio.file.spi.FileTypeDetector;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.SeekableByteChannel;
import java.io.Closeable;
......@@ -2965,7 +2965,63 @@ public final class Files {
}
/**
* Read all the bytes from a file. The method ensures that the file is
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
/**
* Reads all the bytes from an input stream. Uses {@code initialSize} as a hint
* about how many bytes the stream will have.
*
* @param source
* the input stream to read from
* @param initialSize
* the initial size of the byte array to allocate
*
* @return a byte array containing the bytes read from the file
*
* @throws IOException
* if an I/O error occurs reading from the stream
* @throws OutOfMemoryError
* if an array of the required size cannot be allocated
*/
private static byte[] read(InputStream source, int initialSize)
throws IOException
{
int capacity = initialSize;
byte[] buf = new byte[capacity];
int nread = 0;
int n;
for (;;) {
// read to EOF which may read more or less than initialSize (eg: file
// is truncated while we are reading)
while ((n = source.read(buf, nread, capacity - nread)) > 0)
nread += n;
// if last call to source.read() returned -1, we are done
// otherwise, try to read one more byte; if that failed we're done too
if (n < 0 || (n = source.read()) < 0)
break;
// one more byte was read; need to allocate a larger buffer
if (capacity <= MAX_BUFFER_SIZE - capacity) {
capacity = Math.max(capacity << 1, BUFFER_SIZE);
} else {
if (capacity == MAX_BUFFER_SIZE)
throw new OutOfMemoryError("Required array size too large");
capacity = MAX_BUFFER_SIZE;
}
buf = Arrays.copyOf(buf, capacity);
buf[nread++] = (byte)n;
}
return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
}
/**
* Reads all the bytes from a file. The method ensures that the file is
* closed when all bytes have been read or an I/O error, or other runtime
* exception, is thrown.
*
......@@ -2989,22 +3045,13 @@ public final class Files {
* method is invoked to check read access to the file.
*/
public static byte[] readAllBytes(Path path) throws IOException {
try (FileChannel fc = FileChannel.open(path)) {
try (FileChannel fc = FileChannel.open(path);
InputStream is = Channels.newInputStream(fc)) {
long size = fc.size();
if (size > (long)Integer.MAX_VALUE)
if (size > (long)MAX_BUFFER_SIZE)
throw new OutOfMemoryError("Required array size too large");
byte[] arr = new byte[(int)size];
ByteBuffer bb = ByteBuffer.wrap(arr);
while (bb.hasRemaining()) {
if (fc.read(bb) < 0) {
// truncated
break;
}
}
int nread = bb.position();
return (nread == size) ? arr : Arrays.copyOf(arr, nread);
return read(is, (int)size);
}
}
......
......@@ -22,7 +22,7 @@
*/
/* @test
* @bug 7006126
* @bug 7006126 8020669
* @summary Unit test for methods for Files readAllBytes, readAllLines and
* and write methods.
*/
......@@ -82,6 +82,16 @@ public class BytesAndLines {
write(file, lines, Charset.defaultCharset(), opts);
throw new RuntimeException("NullPointerException expected");
} catch (NullPointerException ignore) { }
// read from procfs
if (System.getProperty("os.name").equals("Linux")) {
// Refer to the Linux proc(5) man page for details about /proc/self/stat file
// procfs reports it to be zero sized, even though data can be read from it
String statFile = "/proc/self/stat";
Path pathStat = Paths.get(statFile);
byte[] data = Files.readAllBytes(pathStat);
assertTrue(data.length > 0, "Files.readAllBytes('" + statFile + "') failed to read");
}
}
......@@ -174,6 +184,16 @@ public class BytesAndLines {
throw new RuntimeException("NullPointerException expected");
} catch (NullPointerException ignore) { }
// read from procfs
if (System.getProperty("os.name").equals("Linux")) {
// Refer to the Linux proc(5) man page for details about /proc/self/status file
// procfs reports this file to be zero sized, even though data can be read from it
String statusFile = "/proc/self/status";
Path pathStatus = Paths.get(statusFile);
lines = Files.readAllLines(pathStatus, US_ASCII);
assertTrue(lines.size() > 0, "Files.readAllLines('" + pathStatus + "') failed to read");
}
} finally {
delete(tmpfile);
}
......@@ -242,7 +262,6 @@ public class BytesAndLines {
} finally {
delete(tmpfile);
}
}
static void assertTrue(boolean expr, String errmsg) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册