public CompletableFuture<Integer> frameCountAsync() {
    DebuggerManagerThreadImpl.assertIsManagerThread();
    checkValid();
    if (myFrameCount == -1) {
      ThreadReference threadReference = getThreadReference();
      return DebuggerUtilsAsync.frameCount(threadReference)
        .exceptionally(throwable -> {
          if (throwable instanceof CancellationException cancellationException) {
            throw cancellationException;
          }
          Throwable unwrap = DebuggerUtilsAsync.unwrap(throwable);
          if (unwrap instanceof ObjectCollectedException) {
            return 0;
          }
          else if (unwrap instanceof IncompatibleThreadStateException) {
            final boolean isSuspended;
            try {
              isSuspended = threadReference.isSuspended();
            }
            catch (Throwable ignored) {
              // unable to determine whether the thread is actually suspended, so propagating original exception
              throw new CompletionException(EvaluateExceptionUtil.createEvaluateException(unwrap));
            }
            if (!isSuspended) {
              // give up because it seems to be really resumed
              throw new CompletionException(EvaluateExceptionUtil.createEvaluateException(unwrap));
            }
            else {
              // JDI bug: although isSuspended() == true, frameCount() may throw IncompatibleThreadStateException
              // see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4783403
              // unfortunately, impossible to get this information at the moment, so assume the frame count is null
              return 0;
            }
          }
          else if (unwrap instanceof InternalException) {
            LOG.info(unwrap);
            return 0;
          }
          else {
            if (!getVirtualMachine().canBeModified()) { // do not care in read only vms
              LOG.debug(unwrap);
              return 0;
            }
            else {
              throw (RuntimeException)throwable;
            }
          }
        })
        .thenApply(r -> myFrameCount = r);
    }
    return CompletableFuture.completedFuture(myFrameCount);
  }
public CompletableFuture<Integer> frameCountAsync()