CompletableFuture<StackFrame> () { DebuggerManagerThreadImpl.assertIsManagerThread(); checkValid(); if (myStackFrame == null) { ThreadReference threadRef = myThreadProxy.getThreadReference(); return getFrameIndexAsync().thenCompose(index -> { // batch get frames from 1 to FRAMES_BATCH_MAX // making this number very high does not help much because renderers invocation usually flush all caches if (index > 0 && index < FRAMES_BATCH_MAX) { try { return DebuggerUtilsAsync.frames(threadRef, 0, Math.min(myThreadProxy.frameCount(), FRAMES_BATCH_MAX)) .thenApply(frames -> myStackFrame = frames.get(index)); } catch (EvaluateException e) { return CompletableFuture.failedFuture(e); } } else { return DebuggerUtilsAsync.frame(threadRef, index).thenApply(f -> myStackFrame = f); } }) .exceptionally(throwable -> { if (DebuggerUtilsAsync.unwrap(throwable) instanceof ObjectCollectedException) { throw new CompletionException(EvaluateExceptionUtil.createEvaluateException(JavaDebuggerBundle.message("evaluation.error.thread.collected"))); } throw (RuntimeException)throwable; }); } return CompletableFuture.completedFuture(myStackFrame); }