--- a/src/java.base/share/classes/java/nio/channels/spi/AbstractSelectableChannel.java Wed Apr 18 11:11:38 2018 +0200
+++ b/src/java.base/share/classes/java/nio/channels/spi/AbstractSelectableChannel.java Wed Apr 18 10:20:09 2018 +0100
@@ -108,7 +108,7 @@
if (keys[i] == null)
break;
} else if (keys == null) {
- keys = new SelectionKey[3];
+ keys = new SelectionKey[2];
} else {
// Grow key array
int n = keys.length * 2;
@@ -123,14 +123,14 @@
}
private SelectionKey findKey(Selector sel) {
- synchronized (keyLock) {
- if (keys == null)
- return null;
- for (int i = 0; i < keys.length; i++)
- if ((keys[i] != null) && (keys[i].selector() == sel))
- return keys[i];
+ assert Thread.holdsLock(keyLock);
+ if (keys == null)
return null;
- }
+ for (int i = 0; i < keys.length; i++)
+ if ((keys[i] != null) && (keys[i].selector() == sel))
+ return keys[i];
+ return null;
+
}
void removeKey(SelectionKey k) { // package-private
@@ -166,7 +166,9 @@
}
public final SelectionKey keyFor(Selector sel) {
- return findKey(sel);
+ synchronized (keyLock) {
+ return findKey(sel);
+ }
}
/**
@@ -195,32 +197,31 @@
*
* @throws IllegalArgumentException {@inheritDoc}
*/
- public final SelectionKey register(Selector sel, int ops,
- Object att)
+ public final SelectionKey register(Selector sel, int ops, Object att)
throws ClosedChannelException
{
+ if ((ops & ~validOps()) != 0)
+ throw new IllegalArgumentException();
+ if (!isOpen())
+ throw new ClosedChannelException();
synchronized (regLock) {
- if (!isOpen())
- throw new ClosedChannelException();
- if ((ops & ~validOps()) != 0)
- throw new IllegalArgumentException();
if (isBlocking())
throw new IllegalBlockingModeException();
- SelectionKey k = findKey(sel);
- if (k != null) {
- k.interestOps(ops);
- k.attach(att);
- }
- if (k == null) {
- // New registration
- synchronized (keyLock) {
- if (!isOpen())
- throw new ClosedChannelException();
+ synchronized (keyLock) {
+ // re-check if channel has been closed
+ if (!isOpen())
+ throw new ClosedChannelException();
+ SelectionKey k = findKey(sel);
+ if (k != null) {
+ k.attach(att);
+ k.interestOps(ops);
+ } else {
+ // New registration
k = ((AbstractSelector)sel).register(this, ops, att);
addKey(k);
}
+ return k;
}
- return k;
}
}
@@ -239,12 +240,20 @@
*/
protected final void implCloseChannel() throws IOException {
implCloseSelectableChannel();
+
+ // clone keys to avoid calling cancel when holding keyLock
+ SelectionKey[] copyOfKeys = null;
synchronized (keyLock) {
- int count = (keys == null) ? 0 : keys.length;
- for (int i = 0; i < count; i++) {
- SelectionKey k = keys[i];
- if (k != null)
- k.cancel();
+ if (keys != null) {
+ copyOfKeys = keys.clone();
+ }
+ }
+
+ if (copyOfKeys != null) {
+ for (SelectionKey k : copyOfKeys) {
+ if (k != null) {
+ k.cancel(); // invalidate and adds key to cancelledKey set
+ }
}
}
}