[debugger] IDEA-361080 Add workaround to fix ObjectCollectedException during evaluating conditional breakpoints

(cherry picked from commit 9922fc513d0c4e4d7daa4cc89d078fbb6b5a8f72)

IJ-CR-147314

GitOrigin-RevId: ffc72ca98c6b98842cde50e1a9e76f88c89f9228
This commit is contained in:
Alexey Merkulov
2024-11-21 16:24:36 +00:00
committed by intellij-monorepo-bot
parent 5d73c19f18
commit 720ce629f0
7 changed files with 65 additions and 6 deletions
@@ -28,6 +28,8 @@ public final class EvaluationContextImpl implements EvaluationContext {
private @Nullable ThreadReferenceProxyImpl myPreferableThread = null;
private boolean myMayRetryEvaluation = false;
private EvaluationContextImpl(@NotNull SuspendContextImpl suspendContext,
@Nullable StackFrameProxyImpl frameProxy,
@NotNull DebuggerComputableValue thisObjectComputableValue) {
@@ -177,4 +179,14 @@ public final class EvaluationContextImpl implements EvaluationContext {
return "Evaluating requested on " + myPreferableThread + ", started on " + myThreadForEvaluation + " for " + mySuspendContext;
}
}
@ApiStatus.Internal
public boolean isMayRetryEvaluation() {
return myMayRetryEvaluation;
}
@ApiStatus.Internal
public void setMayRetryEvaluation(boolean mayRetryEvaluation) {
myMayRetryEvaluation = mayRetryEvaluation;
}
}
@@ -16,6 +16,7 @@
package com.intellij.debugger.engine.evaluation.expression;
import com.intellij.debugger.JavaDebuggerBundle;
import com.intellij.debugger.engine.DebuggerUtils;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil;
import com.intellij.debugger.engine.evaluation.EvaluationContext;
@@ -48,7 +49,24 @@ public class ExpressionEvaluatorImpl implements ExpressionEvaluator {
throw EvaluateExceptionUtil.NULL_STACK_FRAME;
}
Object value = myEvaluator.evaluate((EvaluationContextImpl)context);
EvaluationContextImpl evaluationContextImpl = (EvaluationContextImpl)context;
final Object value;
if (evaluationContextImpl.isMayRetryEvaluation()) {
value = DebuggerUtils.getInstance().processCollectibleValue(
() -> myEvaluator.evaluate(evaluationContextImpl),
r -> {
if (r instanceof Value v) {
evaluationContextImpl.keep(v);
}
return r;
},
context
);
}
else {
value = myEvaluator.evaluate(evaluationContextImpl);
}
if (value != null && !(value instanceof Value)) {
throw EvaluateExceptionUtil
@@ -351,14 +351,14 @@ public final class DebuggerUtilsImpl extends DebuggerUtilsEx {
}
@Override
public <R, T extends Value> R processCollectibleValue(
public <R, T> R processCollectibleValue(
@NotNull ThrowableComputable<? extends T, ? extends EvaluateException> valueComputable,
@NotNull Function<? super T, ? extends R> processor,
@NotNull EvaluationContext evaluationContext) throws EvaluateException {
int retries = 3;
while (true) {
T result = valueComputable.compute();
try {
T result = valueComputable.compute();
return processor.apply(result);
}
catch (ObjectCollectedException oce) {
@@ -474,7 +474,15 @@ public abstract class Breakpoint<P extends JavaBreakpointProperties> implements
condition,
this::createConditionCodeFragment));
});
boolean evaluationResult = DebuggerUtilsEx.evaluateBoolean(evaluator, context);
boolean evaluationResult;
try {
if (Registry.is("debugger.retry.conditional.breakpoints", true)) {
context.setMayRetryEvaluation(true);
}
evaluationResult = DebuggerUtilsEx.evaluateBoolean(evaluator, context);
} finally {
context.setMayRetryEvaluation(false);
}
JavaDebuggerEvaluatorStatisticsCollector.logEvaluationResult(myProject, evaluator, true, XEvaluationOrigin.BREAKPOINT_CONDITION);
if (!evaluationResult) {
return false;
@@ -143,7 +143,7 @@ public abstract class DebuggerUtils {
}
@ApiStatus.Internal
public abstract <R, T extends Value> R processCollectibleValue(
public abstract <R, T> R processCollectibleValue(
@NotNull ThrowableComputable<? extends T, ? extends EvaluateException> valueComputable,
@NotNull Function<? super T, ? extends R> processor,
@NotNull EvaluationContext evaluationContext) throws EvaluateException;