mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 04:51:24 +07:00
[debugger] store vm related user data in virtual machine proxy, not in debug process
GitOrigin-RevId: d4ea94a732775782f75ea0cda6f5105328699b0e
This commit is contained in:
committed by
intellij-monorepo-bot
parent
97265aee33
commit
431ced79bc
@@ -95,7 +95,8 @@ public final class AsyncStacksUtils {
|
||||
EvaluationContextImpl evaluationContext = evalContext.withAutoLoadClasses(false);
|
||||
|
||||
DebugProcessImpl process = evaluationContext.getDebugProcess();
|
||||
Pair<ClassType, Method> methodPair = process.getUserData(CAPTURE_STORAGE_METHOD);
|
||||
VirtualMachineProxyImpl virtualMachineProxy = evalContext.getVirtualMachineProxy();
|
||||
Pair<ClassType, Method> methodPair = virtualMachineProxy.getUserData(CAPTURE_STORAGE_METHOD);
|
||||
|
||||
if (methodPair == null) {
|
||||
try {
|
||||
@@ -112,14 +113,13 @@ public final class AsyncStacksUtils {
|
||||
methodPair = NO_CAPTURE_AGENT;
|
||||
LOG.debug("Error loading debug agent", e);
|
||||
}
|
||||
putProcessUserData(CAPTURE_STORAGE_METHOD, methodPair, process);
|
||||
virtualMachineProxy.putUserData(CAPTURE_STORAGE_METHOD, methodPair);
|
||||
}
|
||||
|
||||
if (methodPair == NO_CAPTURE_AGENT) {
|
||||
return null;
|
||||
}
|
||||
|
||||
VirtualMachineProxyImpl virtualMachineProxy = evalContext.getVirtualMachineProxy();
|
||||
List<Value> args = Collections.singletonList(virtualMachineProxy.mirrorOf(getMaxStackLength()));
|
||||
Pair<ClassType, Method> finalMethodPair = methodPair;
|
||||
String value = DebuggerUtils.getInstance().processCollectibleValue(
|
||||
|
||||
@@ -980,7 +980,6 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
|
||||
myReturnValueWatcher = null;
|
||||
myNodeRenderersMap.clear();
|
||||
myRenderers.clear();
|
||||
DebuggerUtils.cleanupAfterProcessFinish(this);
|
||||
myState.compareAndSet(State.DETACHING, State.DETACHED);
|
||||
try {
|
||||
forEachSafe(myDebugProcessListeners, it -> it.processDetached(this, closedByUser));
|
||||
|
||||
@@ -375,13 +375,80 @@ public final class DebuggerUtilsImpl extends DebuggerUtilsEx {
|
||||
}
|
||||
}
|
||||
|
||||
private static final Key<Method> TO_STRING_METHOD_KEY = new Key<>("CachedToStringMethod");
|
||||
|
||||
@Override
|
||||
protected Value internalInvokeInstanceMethod(@NotNull EvaluationContext evaluationContext,
|
||||
@NotNull ObjectReference objRef,
|
||||
@NotNull Method method,
|
||||
@NotNull List<? extends Value> args) throws EvaluateException {
|
||||
return ((EvaluationContextImpl)evaluationContext).getDebugProcess()
|
||||
.invokeInstanceMethod(evaluationContext, objRef, method, args, 0, true);
|
||||
protected String getValueAsStringImpl(@NotNull EvaluationContext evaluationContext, @Nullable Value value) throws EvaluateException {
|
||||
try {
|
||||
if (value == null) {
|
||||
return "null";
|
||||
}
|
||||
if (value instanceof StringReference) {
|
||||
ensureNotInsideObjectConstructor((ObjectReference)value, evaluationContext);
|
||||
return ((StringReference)value).value();
|
||||
}
|
||||
if (isInteger(value)) {
|
||||
return String.valueOf(((PrimitiveValue)value).longValue());
|
||||
}
|
||||
if (value instanceof FloatValue) {
|
||||
return String.valueOf(((FloatValue)value).floatValue());
|
||||
}
|
||||
if (value instanceof DoubleValue) {
|
||||
return String.valueOf(((DoubleValue)value).doubleValue());
|
||||
}
|
||||
if (value instanceof BooleanValue) {
|
||||
return String.valueOf(((PrimitiveValue)value).booleanValue());
|
||||
}
|
||||
if (value instanceof CharValue) {
|
||||
return String.valueOf(((PrimitiveValue)value).charValue());
|
||||
}
|
||||
if (value instanceof ObjectReference objRef) {
|
||||
// We can not pretty print arrays here, otherwise evaluation may fail unexpectedly, check IDEA-358202
|
||||
//if (value instanceof ArrayReference arrayRef) {
|
||||
// final StringJoiner joiner = new StringJoiner(",", "[", "]");
|
||||
// for (final Value element : arrayRef.getValues()) {
|
||||
// joiner.add(getValueAsString(evaluationContext, element));
|
||||
// }
|
||||
// return joiner.toString();
|
||||
//}
|
||||
|
||||
EvaluationContextImpl evaluationContextImpl = (EvaluationContextImpl)evaluationContext;
|
||||
VirtualMachineProxyImpl virtualMachineProxy = evaluationContextImpl.getVirtualMachineProxy();
|
||||
Method toStringMethod = virtualMachineProxy.getUserData(TO_STRING_METHOD_KEY);
|
||||
if (toStringMethod == null) {
|
||||
try {
|
||||
ReferenceType refType = getObjectClassType(objRef.virtualMachine());
|
||||
toStringMethod = findMethod(refType, "toString", "()Ljava/lang/String;");
|
||||
virtualMachineProxy.putUserData(TO_STRING_METHOD_KEY, toStringMethod);
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(
|
||||
JavaDebuggerBundle.message("evaluation.error.cannot.evaluate.tostring", objRef.referenceType().name()));
|
||||
}
|
||||
}
|
||||
if (toStringMethod == null) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(
|
||||
JavaDebuggerBundle.message("evaluation.error.cannot.evaluate.tostring", objRef.referenceType().name()));
|
||||
}
|
||||
Method finalToStringMethod = toStringMethod;
|
||||
return processCollectibleValue(
|
||||
() -> evaluationContextImpl.getDebugProcess()
|
||||
.invokeInstanceMethod(evaluationContext, objRef, finalToStringMethod, Collections.emptyList(), 0, true),
|
||||
result -> {
|
||||
// while result must be of com.sun.jdi.StringReference type, it turns out that sometimes (jvm bugs?)
|
||||
// it is a plain com.sun.tools.jdi.ObjectReferenceImpl
|
||||
if (result == null) {
|
||||
return "null";
|
||||
}
|
||||
return result instanceof StringReference ? ((StringReference)result).value() : result.toString();
|
||||
},
|
||||
evaluationContext);
|
||||
}
|
||||
throw EvaluateExceptionUtil.createEvaluateException(JavaDebuggerBundle.message("evaluation.error.unsupported.expression.type"));
|
||||
}
|
||||
catch (ObjectCollectedException ignored) {
|
||||
throw EvaluateExceptionUtil.OBJECT_WAS_COLLECTED;
|
||||
}
|
||||
}
|
||||
|
||||
// compilable version of array class for compiling evaluator
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
|
||||
import com.intellij.debugger.impl.DebuggerUtilsEx;
|
||||
import com.intellij.debugger.impl.DebuggerUtilsImpl;
|
||||
import com.intellij.debugger.impl.MethodNotFoundException;
|
||||
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
|
||||
import com.intellij.execution.configurations.RunProfile;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.IntelliJProjectUtil;
|
||||
@@ -59,12 +60,13 @@ public final class BatchEvaluator {
|
||||
}
|
||||
}
|
||||
|
||||
public static BatchEvaluator getBatchEvaluator(DebugProcess debugProcess) {
|
||||
BatchEvaluator batchEvaluator = debugProcess.getUserData(BATCH_EVALUATOR_KEY);
|
||||
public static BatchEvaluator getBatchEvaluator(EvaluationContext evaluationContext) {
|
||||
VirtualMachineProxyImpl virtualMachineProxy = ((EvaluationContextImpl)evaluationContext).getVirtualMachineProxy();
|
||||
BatchEvaluator batchEvaluator = virtualMachineProxy.getUserData(BATCH_EVALUATOR_KEY);
|
||||
|
||||
if (batchEvaluator == null) {
|
||||
batchEvaluator = new BatchEvaluator();
|
||||
debugProcess.putUserData(BATCH_EVALUATOR_KEY, batchEvaluator);
|
||||
virtualMachineProxy.putUserData(BATCH_EVALUATOR_KEY, batchEvaluator);
|
||||
}
|
||||
return batchEvaluator;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.debugger.ui.tree.render;
|
||||
|
||||
import com.intellij.debugger.DebuggerContext;
|
||||
@@ -81,7 +81,7 @@ public class ToStringRenderer extends NodeRendererImpl implements OnDemandRender
|
||||
if (value instanceof ObjectReference) {
|
||||
DebuggerUtils.ensureNotInsideObjectConstructor((ObjectReference)value, evaluationContext);
|
||||
}
|
||||
BatchEvaluator.getBatchEvaluator(evaluationContext.getDebugProcess()).invoke(new ToStringCommand(evaluationContext, value) {
|
||||
BatchEvaluator.getBatchEvaluator(evaluationContext).invoke(new ToStringCommand(evaluationContext, value) {
|
||||
@Override
|
||||
public void evaluationResult(String message) {
|
||||
valueDescriptor.setValueLabel(
|
||||
|
||||
@@ -16,7 +16,6 @@ import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.ThrowableComputable;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
@@ -44,7 +43,6 @@ import java.util.function.Function;
|
||||
|
||||
public abstract class DebuggerUtils {
|
||||
private static final Logger LOG = Logger.getInstance(DebuggerUtils.class);
|
||||
private static final Key<Method> TO_STRING_METHOD_KEY = new Key<>("CachedToStringMethod");
|
||||
public static final Set<String> ourPrimitiveTypeNames = Set.of(
|
||||
"byte", "short", "int", "long", "float", "double", "boolean", "char"
|
||||
);
|
||||
@@ -66,86 +64,11 @@ public abstract class DebuggerUtils {
|
||||
return Registry.is("debugger.new.suspend.state.tracking");
|
||||
}
|
||||
|
||||
public static void cleanupAfterProcessFinish(DebugProcess debugProcess) {
|
||||
debugProcess.putUserData(TO_STRING_METHOD_KEY, null);
|
||||
public static @NonNls String getValueAsString(@NotNull EvaluationContext evaluationContext, @Nullable Value value) throws EvaluateException {
|
||||
return getInstance().getValueAsStringImpl(evaluationContext, value);
|
||||
}
|
||||
|
||||
public static @NonNls String getValueAsString(final EvaluationContext evaluationContext, Value value) throws EvaluateException {
|
||||
try {
|
||||
if (value == null) {
|
||||
return "null";
|
||||
}
|
||||
if (value instanceof StringReference) {
|
||||
ensureNotInsideObjectConstructor((ObjectReference)value, evaluationContext);
|
||||
return ((StringReference)value).value();
|
||||
}
|
||||
if (isInteger(value)) {
|
||||
return String.valueOf(((PrimitiveValue)value).longValue());
|
||||
}
|
||||
if (value instanceof FloatValue) {
|
||||
return String.valueOf(((FloatValue)value).floatValue());
|
||||
}
|
||||
if (value instanceof DoubleValue) {
|
||||
return String.valueOf(((DoubleValue)value).doubleValue());
|
||||
}
|
||||
if (value instanceof BooleanValue) {
|
||||
return String.valueOf(((PrimitiveValue)value).booleanValue());
|
||||
}
|
||||
if (value instanceof CharValue) {
|
||||
return String.valueOf(((PrimitiveValue)value).charValue());
|
||||
}
|
||||
if (value instanceof ObjectReference objRef) {
|
||||
// We can not pretty print arrays here, otherwise evaluation may fail unexpectedly, check IDEA-358202
|
||||
//if (value instanceof ArrayReference arrayRef) {
|
||||
// final StringJoiner joiner = new StringJoiner(",", "[", "]");
|
||||
// for (final Value element : arrayRef.getValues()) {
|
||||
// joiner.add(getValueAsString(evaluationContext, element));
|
||||
// }
|
||||
// return joiner.toString();
|
||||
//}
|
||||
|
||||
final DebugProcess debugProcess = evaluationContext.getDebugProcess();
|
||||
Method toStringMethod = debugProcess.getUserData(TO_STRING_METHOD_KEY);
|
||||
if (toStringMethod == null || !toStringMethod.virtualMachine().equals(objRef.virtualMachine())) {
|
||||
try {
|
||||
ReferenceType refType = getObjectClassType(objRef.virtualMachine());
|
||||
toStringMethod = findMethod(refType, "toString", "()Ljava/lang/String;");
|
||||
debugProcess.putUserData(TO_STRING_METHOD_KEY, toStringMethod);
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(
|
||||
JavaDebuggerBundle.message("evaluation.error.cannot.evaluate.tostring", objRef.referenceType().name()));
|
||||
}
|
||||
}
|
||||
if (toStringMethod == null) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(
|
||||
JavaDebuggerBundle.message("evaluation.error.cannot.evaluate.tostring", objRef.referenceType().name()));
|
||||
}
|
||||
Method finalToStringMethod = toStringMethod;
|
||||
DebuggerUtils instance = getInstance();
|
||||
return instance.processCollectibleValue(
|
||||
() -> instance.internalInvokeInstanceMethod(evaluationContext, objRef, finalToStringMethod, Collections.emptyList()),
|
||||
result -> {
|
||||
// while result must be of com.sun.jdi.StringReference type, it turns out that sometimes (jvm bugs?)
|
||||
// it is a plain com.sun.tools.jdi.ObjectReferenceImpl
|
||||
if (result == null) {
|
||||
return "null";
|
||||
}
|
||||
return result instanceof StringReference ? ((StringReference)result).value() : result.toString();
|
||||
},
|
||||
evaluationContext);
|
||||
}
|
||||
throw EvaluateExceptionUtil.createEvaluateException(JavaDebuggerBundle.message("evaluation.error.unsupported.expression.type"));
|
||||
}
|
||||
catch (ObjectCollectedException ignored) {
|
||||
throw EvaluateExceptionUtil.OBJECT_WAS_COLLECTED;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Value internalInvokeInstanceMethod(@NotNull EvaluationContext evaluationContext,
|
||||
@NotNull ObjectReference objRef,
|
||||
@NotNull Method method,
|
||||
@NotNull List<? extends Value> args) throws EvaluateException;
|
||||
protected abstract @NonNls String getValueAsStringImpl(@NotNull EvaluationContext evaluationContext, @Nullable Value value) throws EvaluateException;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public abstract <R, T> R processCollectibleValue(
|
||||
@@ -385,7 +308,7 @@ public abstract class DebuggerUtils {
|
||||
return getSuperTypeInt(subType, superType);
|
||||
}
|
||||
|
||||
private static ReferenceType getObjectClassType(VirtualMachine virtualMachine) {
|
||||
protected static ReferenceType getObjectClassType(VirtualMachine virtualMachine) {
|
||||
return ContainerUtil.getFirstItem(virtualMachine.classesByName(CommonClassNames.JAVA_LANG_OBJECT));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user