Name: nt126004 Date: 04/17/2002
FULL PRODUCT VERSION :
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)
FULL OPERATING SYSTEM VERSION :
Linux sicily 2.4.18-386 #2 Wed Mar 20 20:15:40 EST 2002 i686 unknown
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)
A DESCRIPTION OF THE PROBLEM :
The current bridge from Channels to OutputStream's
does not call flush on the OutputStream when a
WritableByteChannel.write( ) is called.
This causes issues for me when writing data through
OutputStreams that require flushes to push data
to a network or display.
EXPECTED VERSUS ACTUAL BEHAVIOR :
Since the NIO api's don't have a notion of flush,
I think the OutputStream should be flushed on every
write.
This bug can be reproduced always.
CUSTOMER WORKAROUND :
Wrote my own bridge between OutputStream and GatheringByteChannel.
I include the code below and assign the copyright to
Sun Microsystem. As a return, I would love to have
the mail address of somebody I could kvetch
about ByteBuffers.
private static class GatheringByteChannelImpl
extends AbstractInterruptibleChannel // Not really interruptible
implements GatheringByteChannel
{
OutputStream out;
private static final int TRANSFER_SIZE = 8192;
private byte buf[] = new byte[0];
private boolean open = true;
private Object writeLock = new Object();
GatheringByteChannelImpl(OutputStream out) {
this.out = out;
}
public long write(ByteBuffer [] srcs,
int off,
int length)
throws IOException {
if (off < 0 || off >= srcs.length ||
length < 0 || (off + length) > srcs.length) {
throw new IndexOutOfBoundsException();
}
int srcIdx;
long len = 0;
for (srcIdx = off; srcIdx < (off + length); srcIdx++) {
len += srcs[srcIdx].remaining();
}
long totalWritten = 0;
int curSrcIdx = off;
synchronized (writeLock) {
while (totalWritten < len) {
int bytesToWrite = (int)Math.min((len - totalWritten),
(long)TRANSFER_SIZE);
if (buf.length < bytesToWrite)
buf = new byte[bytesToWrite];
{
int offset = 0;
int bytesToCopy = bytesToWrite;
do {
ByteBuffer curSrc = srcs[curSrcIdx];
// Try to copy all that's remaining from
// current buffer
int bytesToGet = bytesToCopy;
// But that may not be possible if there
// isn't enough in the current buffer,
// so copy all we can
if (curSrc.remaining() <= bytesToCopy) {
curSrcIdx++;
bytesToGet = curSrc.remaining();
}
// If there's nothing in this buffer,
// don't bother calling curSrc.get
if (bytesToGet == 0) continue;
curSrc.get(buf, offset, bytesToGet);
bytesToCopy -= bytesToGet;
} while (bytesToCopy > 0);
}
try {
begin();
out.write(buf, 0, bytesToWrite);
} finally {
end(bytesToWrite > 0);
}
totalWritten += bytesToWrite;
}
out.flush();
return totalWritten;
}
}
public long write(ByteBuffer [] srcs)
throws IOException
{
return (write(srcs, 0, srcs.length));
}
public int write(ByteBuffer bb)
throws IOException
{
return ((int)write(new ByteBuffer[] { bb }, 0, 1));
}
protected void implCloseChannel() throws IOException {
out.close();
open = false;
}
}
(Review ID: 145187)
======================================================================
- links to
-
Review openjdk/jdk/13198