code: @Override
    public synchronized void close() throws IOException {
      if (watchdog != null) {
        watchdog.stop();
      }
  
      long timeoutNanos = TimeUnit.SECONDS.toNanos(10);
      long endTimeNanos = System.nanoTime() + timeoutNanos;
      for (ManagedChannel channel : managedChannels) {
        channel.shutdown();
      }
      for (ManagedChannel channel : managedChannels) {
        long awaitTimeNanos = endTimeNanos - System.nanoTime();
        if (awaitTimeNanos <= 0) {
          break;
        }
        try {
          channel.awaitTermination(awaitTimeNanos, TimeUnit.NANOSECONDS);
        } catch (InterruptedException e) {
          Thread.currentThread().interrupt();
          throw new IOException("Interrupted while closing the channelPools");
        }
      }
      for (ManagedChannel channel : managedChannels) {
        if (!channel.isTerminated()) {
          // Sometimes, gRPC channels don't close properly. We cannot explain why that happens,
          // nor can we reproduce the problem reliably. However, that doesn't actually cause
          // problems. Synchronous RPCs will throw exceptions right away. Buffered Mutator based
          // async operations are already logged. Direct async operations may have some trouble,
          // but users should not currently be using them directly.
          //
          // NOTE: We haven't seen this problem since removing the RefreshingChannel
          LOG.info("Could not close %s after 10 seconds.", channel.getClass().getName());
          break;
        }
      }
      managedChannels.clear();
  
      try {
        if (dataGCJClient != null) {
          dataGCJClient.close();
        }
      } catch (Exception ex) {
        throw new IOException("Could not close the data client", ex);
      }
      try {
        if (adminGCJClient != null) {
          adminGCJClient.close();
        }
      } catch (Exception ex) {
        throw new IOException("Could not close the admin client", ex);
      }
  
      BigtableClientMetrics.counter(MetricLevel.Info, "sessions.active").dec();
    }
docs: {@inheritDoc}