English 中文(简体)
Java s ReadableByteChannelImpl inconsistent behaviour
原标题:
  • 时间:2009-12-12 21:17:55
  •  标签:
  • java
  • nio

When I create a channel out of the InputStream with Channels.newChannel(is) java standard library returns a ReadableByteChannelImpl, which is:

   private static class ReadableByteChannelImpl
       extends AbstractInterruptibleChannel    // Not really interruptible
       implements ReadableByteChannel
   {
       InputStream in;
       private static final int TRANSFER_SIZE = 8192;
       private byte buf[] = new byte[0];
       private boolean open = true;
       private Object readLock = new Object();

       ReadableByteChannelImpl(InputStream in) {
           this.in = in;
       }

       public int read(ByteBuffer dst) throws IOException {
           int len = dst.remaining();
           int totalRead = 0;
           int bytesRead = 0;
           synchronized (readLock) {
               while (totalRead < len) {
                   int bytesToRead = Math.min((len - totalRead),
                                              TRANSFER_SIZE);
                   if (buf.length < bytesToRead)
                       buf = new byte[bytesToRead];
                   if ((totalRead > 0) && !(in.available() > 0))
                       break; // block at most once
                   try {
                       begin();
                       bytesRead = in.read(buf, 0, bytesToRead);
                   } finally {
                       end(bytesRead > 0);
                   }
                   if (bytesRead < 0)
                       break;
                   else
                       totalRead += bytesRead;
                   dst.put(buf, 0, bytesRead);
               }
               if ((bytesRead < 0) && (totalRead == 0))
                   return -1;

               return totalRead;
           }
       }

       protected void implCloseChannel() throws IOException {
           in.close();
           open = false;
       }
   }

As you can see it blocks when calling read(ByteBuffer dst) for the first time, and never blocks again. See:

           if ((totalRead > 0) && !(in.available() > 0))
               break; // block at most once

What is the reason behind such a weird behavior?

Also, what is the motivation for extending AbstractInterruptibleChannel without actually making this channel truly interruptible ?

最佳回答

It will not block if it s already read at least one byte and the underlying stream announces that no bytes are available. Note that InputStream#available() can return zero even when some bytes are available, but it should not promise more bytes than can be read without blocking. Hence, this ReadableByteChannel makes an effort to read at least one byte -- assuming the provided ByteBuffer has room for at least one byte -- and, having done so, will not attempt to read the underlying stream again unless the stream is promising that more bytes are available without blocking.

As for why ReadableByteChannelImpl extends AbstractInterruptibleChannel, I suspect that it s to ensure that the wrapped InputStream will be closed properly upon calling Channel#close(), whose contract is further refined by InterruptibleChannel#close(). Extending AbstractInterruptibleChannel allows ReadableByteChannelImpl to borrow its thread-safe opened-closed state guards.

It is a bit of false advertising, as you say, not being truly interruptible, but it is tolerant of being closed from a separate thread, and makes doing so idempotent.

问题回答

暂无回答




相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签