Saturday, June 6, 2009

Problem with Java SocketChannel

Problem with Java SocketChannel

I created a simple java network application and wanted to put it as a service (windows and linux). To do that, I had to implement shutdown mechanism that releases all resources in proper manner for my java app. Obviously, I used Socket (and ServerSocket) class, which runs in separate thread, and used InputStream and OutputStream to read and write data.
So, the problem comes when I need to stop the thread that has Socket which block for incoming data (by invoking read method for example). Clearly, I need to be able to interrupt that blocking point and exit the thread gracefully.
After searching a bit in the internet, I found out about SocketChannel, which implements InterruptibleChannel. This is good, so I could simply send interrupt signal to the thread and the SocketChannel will also get it and quit from blocking state.

But there is a problem (perhaps bug) with the implementation of SocketChannel, that would prevent concurrent read and write to it. Please refer to sun java bug id 4774871 and 4509080.

The work around is like the following (taken from bug #4774871 details):

CUSTOMER WORKAROUND :
The above program works if you change the wrapChannel() method to wrap the SocketChannel to a dummy channel that only forwards the calls to it. It works because it is not an instance of SelectableChannel:


private static ByteChannel wrapChannel(final ByteChannel channel) {

return new ByteChannel() {
public int write(ByteBuffer src) throws IOException {
return channel.write(src);
}

public int read(ByteBuffer dst) throws IOException {
return channel.read(dst);
}

public boolean isOpen() {
return channel.isOpen();
}

public void close() throws IOException {
channel.close();
}
};
}

No comments:

Post a Comment