Search code examples
javaniononblocking

Java: Is SelectionKey.attach() broken?


In my implementation of Java NIO I have not been able to get SelectionKey.attach() to work. Basically, once clients connect (OP_ACCEPT interest ops) I add them to a map where their IP address maps to an object that maintains state for the client. Then, when an OP_READ occurs, I again retrieve the client's IP address, and this time get the value from the map and get the client's state object that way.

The problem here is that I have to do a map lookup EVERY TIME data is read from the network. There is a lot of wasted work going on there. So, I was thrilled to see that you can attach an arbitrary object type to a SelectionKey, which should be easily retrieved when you call SelectionKey.attachment(), even if we are now handling a different event (retrieved during OP_READ versus put into the map during OP_ACCEPT).

The problem is that it doesn't work. When I retrieve the attachment, it is always null. And if I set up the attachment via attach() and then immediately call attachment(), it does work. Somehow between different events, it loses its association.

I'm sorry, my code is a bit long to post here, but if you look at the comments in this thread: link text ...You will see that some others have basically come to the same conclusion: that attach() and attachment() don't work, and never have.

Is there a trick to get it to work, or am I stuck with the evil overhead necessary of manually doing a lookup in a map EVERY TIME there is a new read event to handle?

Finally, is there a way to "wrap" SelectionKey in a new subclass that will properly handle attach() and attachment()?

Thanks!


Solution

  • I have successfully attached objects to SelectionKeys without any problems, but only from the same event. For example the first time I get an OP_READ, I attach an object to the SelectionKey and on subsequent reads I retrieve it, and it works fine. Maybe OP_ACCEPT and OP_READ handle different keys because they're different events, but I think the SelectionKey should be the same for the same connection... however if you make different connections even from the same IP you will get different SelectionKeys.

    UPDATE: I just checked my code and there is something very important: I didn't call attach() at all; I used the SelectableChannel.register(Selector sel, int ops, Object att) method. If you do that, subsequent calls to attachment() on the SelectionKey will work.