docs: public synchronized void close() throws IOException {
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
              Tr.entry(tc, "close");
          }
          if (prepared) {
              // If the channel was prepared, clean up the CompletionKeys
              // and dispose of the channelID
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                  Tr.debug(tc, "close - disposing of socket, channel id: " + channelIdentifier +
                               ", local: " + channel.socket().getLocalSocketAddress() +
                               ", remote: " + channel.socket().getRemoteSocketAddress());
              }
  
              // cancel any timeout entries, since we are closing.
              // since read/writes can be outstanding during channel shutdown
              // we need to at least remove the timeout entries, even if input
              // tracking is not being used.
              if (readFuture != null) {
                  if (readFuture.getTimeoutWorkItem() != null) {
                      if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                          Tr.debug(tc, "cancelling timeout entry. readFuture.getTimeoutWorkItem().state: " + readFuture.getTimeoutWorkItem().state);
                      }
                      readFuture.getTimeoutWorkItem().state = TimerWorkItem.ENTRY_CANCELLED;
                  }
              }
              if (writeFuture != null) {
                  if (writeFuture.getTimeoutWorkItem() != null) {
                      if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                          Tr.debug(tc, "cancelling timeout entry writeFuture.getTimeoutWorkItem().state: " + writeFuture.getTimeoutWorkItem().state);
                      }
                      writeFuture.getTimeoutWorkItem().state = TimerWorkItem.ENTRY_CANCELLED;
                  }
              }
  
              if (channelVCI != null) {
                  if (channelVCI.isInputStateTrackingOperational()) {
                      // need to make sure that any outstanding reads or writes
                      // have been cancelled at the native layer, before
                      // de-initializing objects
  
                      // if channelVCI is not null, then multiIO has been called,
                      // and channelIdentifier must be valid
  
                      if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                          Tr.debug(tc, "Input Tracking (Permission logic) is on");
                      }
  
                      int rc;
  
                      if (channelVCI.isCloseWithReadOutstanding()) {
                          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                              Tr.debug(
                                       tc,
                                       "calling cancel2 on readiocb: channel id: "
                                                       + channelIdentifier
                                                       + "  call id: "
                                                       + readIOCB.getCallIdentifier());
                          }
  
                          rc = provider.cancel2(channelIdentifier, readIOCB.getCallIdentifier());
  
                          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                              Tr.debug(tc, "return from cancel2 rc (0 - success): " + rc);
                          }
                      } else {
                          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                              Tr.debug(tc, "read was not outstanding");
                          }
                      }
  
                      if (channelVCI.isCloseWithWriteOutstanding()) {
                          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                              Tr.debug(
                                       tc,
                                       "calling cancel2 on writeiocb channel id: "
                                                       + channelIdentifier
                                                       + " call id: "
                                                       + writeIOCB.getCallIdentifier());
                          }
  
                          rc = provider.cancel2(channelIdentifier, writeIOCB.getCallIdentifier());
  
                          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                              Tr.debug(tc, "return from cancel2 rc (0 - success): " + rc);
                          }
                      } else {
                          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                              Tr.debug(tc, "write was not outstanding");
                          }
                      }
                  }
              }
  
              provider.terminateIOCB(readIOCB);
              // if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
              // Tr.debug(tc, "putting object in pool, hc: " + readIOCB.hashCode());
              AsyncLibrary.completionKeyPool.put(readIOCB);
  
              provider.terminateIOCB(writeIOCB);
              // if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
              // Tr.debug(tc, "putting object in pool, hc: " + writeIOCB.hashCode());
              AsyncLibrary.completionKeyPool.put(writeIOCB);
  
              provider.dispose(channelIdentifier);
              prepared = false;
          } // end if
  
          channel.close();
  
          super.close();
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
              Tr.exit(tc, "close");
          }
      }