protected void implCloseSelectableChannel() throws IOException {
    synchronized (stateLock) {
      if (state != ST_KILLED) nd.preClose(fd);
      ResourceManager.afterUdpClose();

      // if member of mulitcast group then invalidate all keys
      if (registry != null) registry.invalidateAll();

      long th;
      if ((th = readerThread) != 0) NativeThread.signal(th);
      if ((th = writerThread) != 0) NativeThread.signal(th);
      if (!isRegistered()) kill();
    }
  }
  public int send(ByteBuffer src, SocketAddress target) throws IOException {
    if (src == null) throw new NullPointerException();

    synchronized (writeLock) {
      ensureOpen();
      InetSocketAddress isa = Net.checkAddress(target);
      InetAddress ia = isa.getAddress();
      if (ia == null) throw new IOException("Target address not resolved");
      synchronized (stateLock) {
        if (!isConnected()) {
          if (target == null) throw new NullPointerException();
          SecurityManager sm = System.getSecurityManager();
          if (sm != null) {
            if (ia.isMulticastAddress()) {
              sm.checkMulticast(ia);
            } else {
              sm.checkConnect(ia.getHostAddress(), isa.getPort());
            }
          }
        } else { // Connected case; Check address then write
          if (!target.equals(remoteAddress)) {
            throw new IllegalArgumentException("Connected address not equal to target address");
          }
          return write(src);
        }
      }

      int n = 0;
      try {
        begin();
        if (!isOpen()) return 0;
        writerThread = NativeThread.current();
        do {
          n = send(fd, src, isa);
        } while ((n == IOStatus.INTERRUPTED) && isOpen());

        synchronized (stateLock) {
          if (isOpen() && (localAddress == null)) {
            localAddress = Net.localAddress(fd);
          }
        }
        return IOStatus.normalize(n);
      } finally {
        writerThread = 0;
        end((n > 0) || (n == IOStatus.UNAVAILABLE));
        assert IOStatus.check(n);
      }
    }
  }
 public SocketAddress receive(ByteBuffer dst) throws IOException {
   if (dst.isReadOnly()) throw new IllegalArgumentException("Read-only buffer");
   if (dst == null) throw new NullPointerException();
   synchronized (readLock) {
     ensureOpen();
     // Socket was not bound before attempting receive
     if (localAddress() == null) bind(null);
     int n = 0;
     ByteBuffer bb = null;
     try {
       begin();
       if (!isOpen()) return null;
       SecurityManager security = System.getSecurityManager();
       readerThread = NativeThread.current();
       if (isConnected() || (security == null)) {
         do {
           n = receive(fd, dst);
         } while ((n == IOStatus.INTERRUPTED) && isOpen());
         if (n == IOStatus.UNAVAILABLE) return null;
       } else {
         bb = Util.getTemporaryDirectBuffer(dst.remaining());
         for (; ; ) {
           do {
             n = receive(fd, bb);
           } while ((n == IOStatus.INTERRUPTED) && isOpen());
           if (n == IOStatus.UNAVAILABLE) return null;
           InetSocketAddress isa = (InetSocketAddress) sender;
           try {
             security.checkAccept(isa.getAddress().getHostAddress(), isa.getPort());
           } catch (SecurityException se) {
             // Ignore packet
             bb.clear();
             n = 0;
             continue;
           }
           bb.flip();
           dst.put(bb);
           break;
         }
       }
       return sender;
     } finally {
       if (bb != null) Util.releaseTemporaryDirectBuffer(bb);
       readerThread = 0;
       end((n > 0) || (n == IOStatus.UNAVAILABLE));
       assert IOStatus.check(n);
     }
   }
 }
  // package-private
  int poll(int events, long timeout) throws IOException {
    assert Thread.holdsLock(blockingLock()) && !isBlocking();

    synchronized (readLock) {
      int n = 0;
      try {
        begin();
        synchronized (stateLock) {
          if (!isOpen()) return 0;
          readerThread = NativeThread.current();
        }
        n = Net.poll(fd, events, timeout);
      } finally {
        readerThread = 0;
        end(n > 0);
      }
      return n;
    }
  }
 public int write(ByteBuffer buf) throws IOException {
   if (buf == null) throw new NullPointerException();
   synchronized (writeLock) {
     synchronized (stateLock) {
       ensureOpen();
       if (!isConnected()) throw new NotYetConnectedException();
     }
     int n = 0;
     try {
       begin();
       if (!isOpen()) return 0;
       writerThread = NativeThread.current();
       do {
         n = IOUtil.write(fd, buf, -1, nd);
       } while ((n == IOStatus.INTERRUPTED) && isOpen());
       return IOStatus.normalize(n);
     } finally {
       writerThread = 0;
       end((n > 0) || (n == IOStatus.UNAVAILABLE));
       assert IOStatus.check(n);
     }
   }
 }
 public long write(ByteBuffer[] srcs, int offset, int length) throws IOException {
   if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
     throw new IndexOutOfBoundsException();
   synchronized (writeLock) {
     synchronized (stateLock) {
       ensureOpen();
       if (!isConnected()) throw new NotYetConnectedException();
     }
     long n = 0;
     try {
       begin();
       if (!isOpen()) return 0;
       writerThread = NativeThread.current();
       do {
         n = IOUtil.write(fd, srcs, offset, length, nd);
       } while ((n == IOStatus.INTERRUPTED) && isOpen());
       return IOStatus.normalize(n);
     } finally {
       writerThread = 0;
       end((n > 0) || (n == IOStatus.UNAVAILABLE));
       assert IOStatus.check(n);
     }
   }
 }