void releaseBuffers() {
   for (int i = 0; i < numBufs; i++) {
     if (!(bufs[i] instanceof DirectBuffer)) {
       Util.releaseTemporaryDirectBuffer(shadow[i]);
     }
   }
 }
  private int send(FileDescriptor fd, ByteBuffer src, SocketAddress target) throws IOException {
    if (src instanceof DirectBuffer) return sendFromNativeBuffer(fd, src, target);

    // Substitute a native buffer
    int pos = src.position();
    int lim = src.limit();
    assert (pos <= lim);
    int rem = (pos <= lim ? lim - pos : 0);

    ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
    try {
      bb.put(src);
      bb.flip();
      // Do not update src until we see how many bytes were written
      src.position(pos);

      int n = sendFromNativeBuffer(fd, bb, target);
      if (n > 0) {
        // now update src
        src.position(pos + n);
      }
      return n;
    } finally {
      Util.releaseTemporaryDirectBuffer(bb);
    }
  }
 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);
     }
   }
 }
  private int receive(FileDescriptor fd, ByteBuffer dst) throws IOException {
    int pos = dst.position();
    int lim = dst.limit();
    assert (pos <= lim);
    int rem = (pos <= lim ? lim - pos : 0);
    if (dst instanceof DirectBuffer && rem > 0) return receiveIntoNativeBuffer(fd, dst, rem, pos);

    // Substitute a native buffer. If the supplied buffer is empty
    // we must instead use a nonempty buffer, otherwise the call
    // will not block waiting for a datagram on some platforms.
    int newSize = Math.max(rem, 1);
    ByteBuffer bb = Util.getTemporaryDirectBuffer(newSize);
    try {
      int n = receiveIntoNativeBuffer(fd, bb, newSize, 0);
      bb.flip();
      if (n > 0 && rem > 0) dst.put(bb);
      return n;
    } finally {
      Util.releaseTemporaryDirectBuffer(bb);
    }
  }