Code Painters The Art of Coding


Why java.nio is a better idea for Android

In my recent Android project I've encountered totally unexpected, low-level problems with TCP sockets. The problem occurs when you try to interrupt a blocking socket I/O by closing the socket. It is expected for the blocked operation to throw a SocketError exception immediately when the socket is closed from another thread (that's the only way to interrupt blocking socket operation, actually - Thread.interrupt() doesn't abort blocked I/O).

The first problem I've hit trying to abort Socket.connect(address, timeout). Closing the socket doesn't interrupt connect(), it remains blocked until the timeout. The problem is there up to and including Android 4.0.3. Here's a bug report #24318 opened by me - the problem was confirmed and fixed.

As a workaround I've tried to use java.nio API when connecting, and then continue with the plain, old streams API (the idea was to make as little modifications to the existing code as possible). This solved the connect() problem, but immediately revealed another issue - concurrent read/write on the socket blocks each other. Fortunately, I've found Sun's #4774871 bug report which explains the problem and gives a good workaround. Android (at least 2.3.x, I had no time to check other versions) is also affected.

But that's not the whole story. Up to and including Android 2.2, blocking read from a socket also can't be easily interrupted. This issue seems to be corrected in Android 2.3, see #7933. Unfortunately, there's no reliable workaround.

The moral of the story is to use java.nio API instead, as its implementation is free of the issues described above.

  • Facebook
  • Digg
  • Twitter
  • LinkedIn
  • Google Bookmarks
  • Reddit
  • StumbleUpon