RFR: 6478546: FileInputStream.read() throws OutOfMemoryError when there is plenty available
Brian Burkhalter
bpb at openjdk.java.net
Tue Apr 19 21:11:26 UTC 2022
On Thu, 14 Apr 2022 06:23:24 GMT, Alan Bateman <alanb at openjdk.org> wrote:
>> Modify native multi-byte read-write code used by the `java.io` classes to limit the size of the allocated native buffer thereby decreasing off-heap memory footprint and increasing throughput.
>
> src/java.base/share/native/libjava/io_util.c line 133:
>
>> 131: if (nread == 0)
>> 132: nread = -1;
>> 133: break;
>
> Can you prototype doing the loop in Java rather than in native code so that there is less native code to maintain?
I prototyped doing the read loop in Java and the performance seemed to be about the same. The problem is that the loop needs to exit when the native `read()` function performs a short read, i.e., fewer bytes are read than were requested. Without this, at least one regression test fails. The reason is not completely clear.
To detect such a short read in the Java layer would require some way for the native layer to notify the Java layer. One potential such method is
boolean readBytes(byte[] b, int off, int len, int[] nread) {}
where the return value indicates whether all or only some of the `len` bytes were read. If not all were read, then `nread[0]` would contain the number actually read or `-1`.
Another possibility is
int readBytes(byte[] b, int off, int len, int maxBufferSize) {}
which is identical to the current `readBytes()` except that the maximum transfer buffer size is specified as a method parameter instead of being defined by a symbolic constant in the native layer. In this case a short read would be detected if `len >= maxBufferSize` and the returned value is less than `maxBufferSize`.
As for the read loop being in native code, note that the write loop is also already in native code, so if the read loop were moved to Java, then probably the write loop should be as well.
One advantage of the loops being in native code is that there is only one `malloc()` per Java `read(byte[],int,int)` or `write(byte[],int,int)` invocation.
-------------
PR: https://git.openjdk.java.net/jdk/pull/8235
More information about the core-libs-dev
mailing list