-
Bug
-
Resolution: Fixed
-
P4
-
1.4.1
-
mantis
-
x86
-
windows_2000
-
Verified
Name: gm110360 Date: 08/26/2002
FULL PRODUCT VERSION :
j2sdk-1_4_1-rc-windows-i586.exe
Java 2 Enterprise Edition version 1.3.1, build 1.3.1-b17
FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]
A DESCRIPTION OF THE PROBLEM :
I have a NIO Client and Server using non-bloacking mode.
When client connects to the server the selector respond
back saying
Connecting ....
Processing selecion key.isConnectable()=true key.isReadable
()=false
which is correct. Then i wait till finishConnect() and
write something on the stream to send to server. Server
respond back.
This time when the selector returns back on the client side
it still show me isConnectable() = true ??
Processing selecion key.isConnectable()=true key.isReadable
()=true
And the while loop
while ( selector.select() > 0 ) {
keeps on executing and behave like while(true).
REGRESSION. Last worked in version 1.4
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Please find the source attached.
1.Execute the Server
2. Execute the client
EXPECTED VERSUS ACTUAL BEHAVIOR :
The client will keep on recursively sending data to server
as the loop
while ( selector.select() > 0 ) {
behaves as if while(true)
this happens on the client side
ERROR MESSAGES/STACK TRACES THAT OCCUR :
This is a problem of selector reporting.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
######################### CLIENT CODE ##################################
import java.nio.*;
import java.nio.charset.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class NIOClient {
public static void main(String[] args) {
System.out.println("Connecting ....");
connect();
System.out.println("Connected.");
}
public static void connect() {
try{
java.net.InetAddress lh =
java.net.InetAddress.getLocalHost();
java.net.InetSocketAddress socketAddress = new
java.net.InetSocketAddress(lh, 5555);
java.nio.charset.Charset charset =
java.nio.charset.Charset.forName("us-ascii");
java.nio.charset.CharsetEncoder encoder =
charset.newEncoder();
java.nio.charset.CharsetDecoder decoder =
charset.newDecoder();
//allocate buffers
ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
CharBuffer charBuffer = CharBuffer.allocate(1024);
java.nio.channels.SocketChannel channel =
java.nio.channels.SocketChannel.open();
// make the channel as non-blocking
channel.configureBlocking(false);
// for a non-blocking io it should written immediately
channel.connect(socketAddress);
//get the selector
//java.nio.channels.Selector selector =
java.nio.channels.Selector.open();
java.nio.channels.Selector selector =
java.nio.channels.spi.SelectorProvider.provider().openSelector();
//register the channel
channel.register(selector,
java.nio.channels.SelectionKey.OP_CONNECT |
java.nio.channels.SelectionKey.OP_READ );
while ( selector.select() > 0 ) {
// get the set of ready object
java.util.Set keys = selector.selectedKeys();
java.util.Iterator readyItor = keys.iterator();
//walk through the set
while ( readyItor.hasNext() ) {
// get the ket from the set
java.nio.channels.SelectionKey key =
(java.nio.channels.SelectionKey)readyItor.next();
//remove the current entry
readyItor.remove();
// get the channel
java.nio.channels.SocketChannel
keyChannel = (java.nio.channels.SocketChannel)key.channel();
System.out.println("Processing selecion
key.isConnectable()=" + key.isConnectable() + " key.isReadable()=" +
key.isReadable() );
if ( key.isConnectable() ) {
//Finish connection
if (
keyChannel.isConnectionPending() ) {
keyChannel.finishConnect
();
}
String request = "Hello, how
are you ?\n";
keyChannel.write(encoder.encode
( CharBuffer.wrap(request) ));
//clear the buffers
buffer.clear();
charBuffer.clear();
} else if( key.isReadable() ) {
ByteBuffer byteBuffer =
ByteBuffer.allocate(1024);
int nbytes = keyChannel.read(
byteBuffer );
byteBuffer.flip();
String result = decode(
byteBuffer );
System.out.println(result);
//clear the buffers
buffer.clear();
charBuffer.clear();
} else {
System.out.println("Ooops");
}
}
}
} catch ( java.lang.IllegalArgumentException iae ) {
iae.printStackTrace();
} catch ( java.nio.channels.NotYetConnectedException nyce ) {
nyce.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public static String decode( ByteBuffer byteBuffer ) throws
java.nio.charset.CharacterCodingException{
Charset charset = Charset.forName("us-ascii");
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode( byteBuffer );
String result = charBuffer.toString();
return result;
}
}
######################### SERVER CODE ##################################
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
class NIOServer implements Runnable {
int port = 5555;
static final int BUFSIZE = 30;
java.nio.channels.Selector selector = null;
java.nio.channels.ServerSocketChannel selectableChannel = null;
java.util.Vector list = new java.util.Vector();
int keysAdded = 0;
static String QUIT_SERVER = "quit";
static String SHUTDOWN = "shutdown";
public NIOServer() {
}
public NIOServer(int port) {
this.port = port;
}
public void initialize () throws java.io.IOException {
this.selector = java.nio.channels.spi.SelectorProvider.provider
().openSelector();
this.selectableChannel =
java.nio.channels.ServerSocketChannel.open();
this.selectableChannel.configureBlocking(false);
java.net.InetAddress lh = java.net.InetAddress.getLocalHost();
java.net.InetSocketAddress isa = new java.net.InetSocketAddress
(lh, this.port);
this.selectableChannel.socket().bind(isa);
}
protected void finalize() throws java.io.IOException {
this.selectableChannel.close();
this.selector.close();
}
public void log(String msg) {
System.out.println(msg);
}
public void acceptConnections() {
try {
//register the channel
java.nio.channels.SelectionKey acceptKey =
this.selectableChannel.register(this.selector,
java.nio.channels.SelectionKey.OP_ACCEPT);
this.log("Acceptor loop...");
// walk through the keys
while ( (this.keysAdded = acceptKey.selector().select
()) > 0 ) {
this.log("Selector returned " + this.keysAdded
+ " ready for IO operation.");
//get the ready set of objects
java.util.Set readyKeys = selector.selectedKeys
();
java.util.Iterator i = readyKeys.iterator();
while( i.hasNext() ) {
java.nio.channels.SelectionKey key =
(java.nio.channels.SelectionKey)i.next();
i.remove();
if ( key.isAcceptable() ) {
// get the channel accociated
with this key
java.nio.channels.ServerSocketChannel nextReady =
(java.nio.channels.ServerSocketChannel)key.channel();
this.log("Processing selecion
key read=" + key.isReadable() + " write=" + key.isWritable() + " accept=" +
key.isAcceptable() );
java.nio.channels.SocketChannel
channel = nextReady.accept();
channel.configureBlocking
(false);
java.nio.channels.SelectionKey
readyKey =
channel.register
(this.selector, java.nio.channels.SelectionKey.OP_READ);
ChannelCallback cc = new
ChannelCallback(channel);
readyKey.attach(cc);
//add to the list
this.list.add(cc);
} else if ( key.isReadable() ) {
// get the channel accociated
with this key
java.nio.channels.SelectableChannel nextReady =
(java.nio.channels.SelectableChannel)key.channel();
this.log("Processing selecion
key read=" + key.isReadable() + " write=" + key.isWritable() + " accept=" +
key.isAcceptable() );
ChannelCallback cc =
(ChannelCallback)key.attachment();
this.readMessage(cc);
}
}
}
} catch (Exception e) {
}
this.log("End of acceptor loop.");
}
public void writeMessage(java.nio.channels.SocketChannel channel,
String message) throws java.io.IOException {
ByteBuffer buf = ByteBuffer.wrap( message.getBytes() );
int nbytes = channel.write(buf);
this.log("Wrote " + nbytes + " to channel.");
}
public String decode( ByteBuffer byteBuffer ) throws
java.nio.charset.CharacterCodingException{
Charset charset = Charset.forName("us-ascii");
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode( byteBuffer );
String result = charBuffer.toString();
return result;
}
public void readMessage( ChannelCallback callback ) throws
java.lang.InterruptedException {
ByteBuffer byteBuffer = ByteBuffer.allocate(BUFSIZE);
try {
int nbytes = callback.getChannel().read( byteBuffer );
byteBuffer.flip();
String result = this.decode( byteBuffer );
if (result.indexOf("quit") >= 0 ) {
callback.getChannel().close();
} else if ( result.indexOf("shutdown") >= 0 ){
callback.getChannel().close();
throw new java.lang.InterruptedException();
} else {
callback.append( result );
if ( result.indexOf("\n") >= 0 ) {
//if we are done with the line then we
execute the callback
callback.execute();
}
}
} catch (java.io.IOException ioe) {
//System.out.println("Removing the channel from the
list.");
this.list.remove(callback);
}
}
public static void main(String[] args)
{
System.out.println("Hello World!");
NIOServer nioServer = new NIOServer();
try {
nioServer.initialize();
} catch(Exception e) {
e.printStackTrace();
}
Thread t = new Thread(nioServer);
t.start();
try {
nioServer.acceptConnections();
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
while (true) {
System.out.println(list.size());
java.util.Enumeration enum = list.elements();
while( enum.hasMoreElements() ) {
ChannelCallback cc = (ChannelCallback)
(enum.nextElement());
try {
writeMessage(cc.getChannel(), "I am
fine thanx.");
} catch (Exception e){
e.printStackTrace();
list.remove(cc);
}
}
try {
Thread.sleep(10000);
} catch (Exception e){}
}
}
class ChannelCallback {
private SocketChannel channel;
private StringBuffer buffer;
public ChannelCallback( java.nio.channels.SocketChannel
channel ) {
this.channel = channel;
buffer = new StringBuffer();
}
public void execute() throws IOException {
System.out.println(this.buffer.toString());
writeMessage( this.channel, this.buffer.toString() );
buffer = new StringBuffer();
}
public SocketChannel getChannel() {
return this.channel;
}
public void append(String values) {
this.buffer.append(values);
}
};
}
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
If you execute this with the previous version
java version "1.4.0_01"
Java(TM) 2 Runtime Environment, Standard Edition (build
1.4.0_01-b03)
Java HotSpot(TM) Client VM (build 1.4.0_01-b03, mixed mode)
The same sample code works fine.
Release Regression From : 1.4.0_01
The above release value was the last known release where this
bug was known to work. Since then there has been a regression.
(Review ID: 163533)
======================================================================
- relates to
-
JDK-4750577 (ch spec) SelectionKey.isConnectable spec clarification
-
- Open
-