CompletableFuture<Integer> () { DebuggerManagerThreadImpl.assertIsManagerThread(); checkValid(); if (myFrameCount == -1) { ThreadReference threadReference = getThreadReference(); return DebuggerUtilsAsync.frameCount(threadReference) .exceptionally(throwable -> { 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); }