JDK-8198672 : (ch) Separate blocking and non-blocking code paths
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.nio
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 11
  • Submitted: 2018-02-25
  • Updated: 2018-05-14
  • Resolved: 2018-05-14
Related Reports
CSR :  
Description
Summary
-------

Improve the performance and reliability of the java.nio.channel.SelectableChannel implementations by separating the blocking and non-blocking code paths.

Problem
-------

SocketChannel, ServerSocketChannel, DatagramChannel, Pipe.SourceChannel and Pipe.SinkChannel implement InterruptibleChannel so that blocking I/O operations can be interrupted (and the channel closed) by Thread.interrupt. This behavior is problematic for high-performance libraries that use non-blocking I/O. Interrupting a thread has the potential to close a random channel that the thread happens to perform an I/O operation on. In addition, the implementation of async close and interrupt has been highly problematic with reliability issues and complex synchronization adding significant overhead to performance critical code paths.

Usability, reliability, and performance can been improved significantly by limiting interruption to channels that are configured blocking. However, re-implementing this complex area results in a few behavior changes:

1. Invoking configureBlocking(true) on a selectable channel will now block until outstanding I/O operations have completed. The specification allows this but the implementation in the JDK didn't historically synchronize and so didn't block. While unlikely, this may be observable by code outside of the JDK that has assumed it can change a selectable channel to non-blocking whilst a thread is blocked in an I/O operation.

2. Invoking an I/O operation on a channel configured non-blocking and with the interrupt status set no longer closes the channel. This will be welcomed by many but it's possible (although unlikely) that something depends on long standing and unspecified behavior.

3. Closing a connected SocketChannel that is registered with a `Selector` will delay closing the connection until the closed channel is flushed from all Selectors that it is registered with. The long standing behavior has been to close the connection (at least on Linux and macOS, not Windows) and to delay closing the file descriptor until the closed channel is flushed from all Selectors. The change is necessary for reliability reasons but it may be observed in environments that do not perform any selection operations to flush closed channels. To mitigate this behavior change, the implementation will shutdown the connection for writing so that at least the peer will read EOF. However the new behavior may initially puzzle developers that use `netstat` and other networking tools to get information about network connections.


Solution
--------

Re-implement the I/O operations (read, write, accept, connect, finishConnect) defined by SocketChannel, ServerSocketChannel, DatagramChannel, Pipe.SourceChannel and Pipe.SinkChannel. When configured blocking, any thread that potentially blocks on an I/O operation can be interrupted so that the I/O operation is aborted and the channel closed as per the InterruptibleChannel specification. When configured non-blocking threads doing non-blocking I/O operations can be interrupted (meaning their interrupt status is set) but the channel is not closed.


Specification
-------------

There are no specification changes as InterruptibleChannel does not specify the behavior for non-blocking I/O operations.


Comments
Re-approve the amended request.
14-05-2018

I've updated this CSR to list an additional behaviorall difference (point #3). This additional item does not change the overall compatibility risk. The release note has/will be updated to list this point.
14-05-2018

Krushnareddy - I think you have added a comment to the wrong CSR. The issue tracking clarifications to the exceptions thrown by DatagramChannel is JDK-8198753. The question of which exception is thrown when there are several choices is not specified in this API.
16-03-2018

[~alanb] Thanks. I did not know there is a separate CSR as it's in draft state. I left the comment here primarily due to the changes done as part of this CSR affects a test in JCK, because of stated reason. Now that we have a CSR(JDK-8199195) in place, I will post this comment there.
16-03-2018

Is it worth to specify -- "UnsupportedAddressTypeException - If the type of the given address is not supported" for the method public abstract DatagramChannel connect���(SocketAddress remote) throws IOException In DatagramChannel. it's necessary with the modified code as part of this CSR that, it will throw UnsupportedAddressTypeException if the socketAddress is invalid before checking the channel is open? It's in the context that : if a piece of code closes the socket associated with the channel and calling channel.connect("invalid socket") expects ClosedChannelException. But it encounters the unspecified "UnsupportedAddressTypeException" for the connect method.
16-03-2018

With plans for a release note already in place, moving to Approved.
28-02-2018