Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

6478546: FileInputStream.read() throws OutOfMemoryError when there is plenty available #8235

Closed
wants to merge 16 commits into from
37 changes: 20 additions & 17 deletions src/java.base/share/classes/java/io/FileInputStream.java
Expand Up @@ -27,6 +27,7 @@

import java.nio.channels.FileChannel;
import java.util.Arrays;
import java.util.Objects;
import jdk.internal.misc.Blocker;
import jdk.internal.util.ArraysSupport;
import sun.nio.ch.FileChannelImpl;
Expand Down Expand Up @@ -243,13 +244,25 @@ public int read() throws IOException {
private native int read0() throws IOException;

/**
* Reads a subarray as a sequence of bytes.
* @param b the data to be written
* @param off the start offset in the data
* @param len the number of bytes that are written
* Reads a sub-array as a sequence of bytes.
* @param b the buffer into which the data is read.
* @param off the start offset of the data.
* @param len the number of bytes to read.
* @throws IOException If an I/O error has occurred.
*/
private native int readBytes(byte[] b, int off, int len) throws IOException;
private int readBytes(byte[] b, int off, int len) throws IOException {
Objects.checkFromIndexSize(off, len, b.length);
if (len == 0)
return 0;
long comp = Blocker.begin();
try {
return readBytes0(b, off, len);
} finally {
Blocker.end(comp);
}
}

private native int readBytes0(byte[] b, int off, int len) throws IOException;

/**
* Reads up to {@code b.length} bytes of data from this input
Expand All @@ -264,12 +277,7 @@ public int read() throws IOException {
*/
@Override
public int read(byte[] b) throws IOException {
long comp = Blocker.begin();
try {
return readBytes(b, 0, b.length);
} finally {
Blocker.end(comp);
}
return readBytes(b, 0, b.length);
}

/**
Expand All @@ -288,12 +296,7 @@ public int read(byte[] b) throws IOException {
*/
@Override
public int read(byte[] b, int off, int len) throws IOException {
long comp = Blocker.begin();
try {
return readBytes(b, off, len);
} finally {
Blocker.end(comp);
}
return readBytes(b, off, len);
}

@Override
Expand Down
47 changes: 26 additions & 21 deletions src/java.base/share/classes/java/io/FileOutputStream.java
Expand Up @@ -26,6 +26,7 @@
package java.io;

import java.nio.channels.FileChannel;
import java.util.Objects;
import jdk.internal.access.SharedSecrets;
import jdk.internal.access.JavaIOFileDescriptorAccess;
import jdk.internal.misc.Blocker;
Expand Down Expand Up @@ -305,7 +306,7 @@ private void open(String name, boolean append) throws FileNotFoundException {
* @param append {@code true} if the write operation first
* advances the position to the end of file
*/
private native void write(int b, boolean append) throws IOException;
private native void write0(int b, boolean append) throws IOException;

/**
* Writes the specified byte to this file output stream. Implements
Expand All @@ -319,22 +320,36 @@ public void write(int b) throws IOException {
boolean append = fdAccess.getAppend(fd);
long comp = Blocker.begin();
try {
write(b, append);
write0(b, append);
} finally {
Blocker.end(comp);
}
}

/**
* Writes a sub array as a sequence of bytes.
* @param b the data to be written
* @param off the start offset in the data
* @param len the number of bytes that are written
* @param append {@code true} to first advance the position to the
* end of file
* Writes a sub-array as a sequence of bytes.
*
* @param b the data to be written
* @param off the start offset in the data
* @param len the number of bytes that are written
* @param append {@code true} to first advance the position to the
* end of file
* @throws IOException If an I/O error has occurred.
*/
private native void writeBytes(byte[] b, int off, int len, boolean append)
private void writeBytes(byte[] b, int off, int len, boolean append)
throws IOException {
Objects.checkFromIndexSize(off, len, b.length);
if (len == 0)
return;
long comp = Blocker.begin();
try {
writeBytes0(b, off, len, append);
} finally {
Blocker.end(comp);
}
}

private native void writeBytes0(byte[] b, int off, int len, boolean append)
throws IOException;

/**
Expand All @@ -347,12 +362,7 @@ private native void writeBytes(byte[] b, int off, int len, boolean append)
@Override
public void write(byte[] b) throws IOException {
boolean append = fdAccess.getAppend(fd);
long comp = Blocker.begin();
try {
writeBytes(b, 0, b.length, append);
} finally {
Blocker.end(comp);
}
writeBytes(b, 0, b.length, append);
}

/**
Expand All @@ -367,12 +377,7 @@ public void write(byte[] b) throws IOException {
@Override
public void write(byte[] b, int off, int len) throws IOException {
boolean append = fdAccess.getAppend(fd);
long comp = Blocker.begin();
try {
writeBytes(b, off, len, append);
} finally {
Blocker.end(comp);
}
writeBytes(b, off, len, append);
}

/**
Expand Down
11 changes: 9 additions & 2 deletions src/java.base/share/classes/java/io/RandomAccessFile.java
Expand Up @@ -26,6 +26,7 @@
package java.io;

import java.nio.channels.FileChannel;
import java.util.Objects;

import jdk.internal.access.JavaIORandomAccessFileAccess;
import jdk.internal.access.SharedSecrets;
Expand Down Expand Up @@ -378,13 +379,16 @@ public int read() throws IOException {
private native int read0() throws IOException;

/**
* Reads a sub array as a sequence of bytes.
* Reads a sub-array as a sequence of bytes.
* @param b the buffer into which the data is read.
* @param off the start offset of the data.
* @param len the number of bytes to read.
* @throws IOException If an I/O error has occurred.
*/
private int readBytes(byte[] b, int off, int len) throws IOException {
Objects.checkFromIndexSize(off, len, b.length);
if (len == 0)
return 0;
long comp = Blocker.begin();
try {
return readBytes0(b, off, len);
Expand Down Expand Up @@ -549,14 +553,17 @@ public void write(int b) throws IOException {
private native void write0(int b) throws IOException;

/**
* Writes a sub array as a sequence of bytes.
* Writes a sub-array as a sequence of bytes.
*
* @param b the data to be written
* @param off the start offset in the data
* @param len the number of bytes that are written
* @throws IOException If an I/O error has occurred.
*/
private void writeBytes(byte[] b, int off, int len) throws IOException {
Objects.checkFromIndexSize(off, len, b.length);
if (len == 0)
return;
long comp = Blocker.begin();
try {
writeBytes0(b, off, len);
Expand Down
2 changes: 1 addition & 1 deletion src/java.base/share/native/libjava/FileInputStream.c
Expand Up @@ -67,7 +67,7 @@ Java_java_io_FileInputStream_read0(JNIEnv *env, jobject this) {
}

JNIEXPORT jint JNICALL
Java_java_io_FileInputStream_readBytes(JNIEnv *env, jobject this,
Java_java_io_FileInputStream_readBytes0(JNIEnv *env, jobject this,
jbyteArray bytes, jint off, jint len) {
return readBytes(env, this, bytes, off, len, fis_fd);
}
Expand Down
4 changes: 2 additions & 2 deletions src/java.base/share/native/libjava/FileOutputStream.c
Expand Up @@ -60,12 +60,12 @@ Java_java_io_FileOutputStream_open0(JNIEnv *env, jobject this,
}

JNIEXPORT void JNICALL
Java_java_io_FileOutputStream_write(JNIEnv *env, jobject this, jint byte, jboolean append) {
Java_java_io_FileOutputStream_write0(JNIEnv *env, jobject this, jint byte, jboolean append) {
writeSingle(env, this, byte, append, fos_fd);
}

JNIEXPORT void JNICALL
Java_java_io_FileOutputStream_writeBytes(JNIEnv *env,
Java_java_io_FileOutputStream_writeBytes0(JNIEnv *env,
jobject this, jbyteArray bytes, jint off, jint len, jboolean append) {
writeBytes(env, this, bytes, off, len, append, fos_fd);
}
Expand Down