From 4e9e87fda729e98e776f6cfb25bb8cb7a54abeef Mon Sep 17 00:00:00 2001 From: Nikita Nazarov Date: Wed, 7 Oct 2020 12:56:40 +0300 Subject: [PATCH] IJ-CR-3115: Add agent actions timeouts (cherry picked from commit 4cbeb8a4a1755d5dbfba9e3d44205d3c090630d7) GitOrigin-RevId: 6225c47ce482c2ddba1a8fec98f11b8755f53700 --- .../action/CalculateRetainedSizeAction.java | 18 ++- .../CalculationTimeoutReferringObject.java | 91 ++++++++++++ .../agent/CompoundRootReferringObject.java | 97 +++++++++++++ .../memory/agent/GCRootReferringObject.java | 7 +- .../memory/agent/JNILocalReferringObject.java | 22 +++ .../debugger/memory/agent/MemoryAgent.java | 44 +++--- .../memory/agent/MemoryAgentActionResult.java | 32 +++++ .../memory/agent/MemoryAgentImpl.java | 53 ++++--- .../memory/agent/MemoryAgentOperations.java | 135 +++++++++++++----- ...oryAgentPathsToClosestGCRootsProvider.java | 6 +- .../memory/agent/MemoryAgentUtil.java | 8 +- .../agent/StackLocalReferringObject.java | 6 +- .../debugger/memory/agent/parsers/Parsers.kt | 45 ++++-- .../memory/agent/ui/RetainedSizeDialog.java | 43 +++--- .../memory/agent/extractor/AgentExtractor.kt | 30 ++-- .../messages/JavaDebuggerBundle.properties | 3 +- .../src/messages/ActionsBundle.properties | 2 + .../util/resources/misc/registry.properties | 2 + 18 files changed, 518 insertions(+), 126 deletions(-) create mode 100644 java/debugger/impl/src/com/intellij/debugger/memory/agent/CalculationTimeoutReferringObject.java create mode 100644 java/debugger/impl/src/com/intellij/debugger/memory/agent/CompoundRootReferringObject.java create mode 100644 java/debugger/impl/src/com/intellij/debugger/memory/agent/JNILocalReferringObject.java create mode 100644 java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgentActionResult.java diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/action/CalculateRetainedSizeAction.java b/java/debugger/impl/src/com/intellij/debugger/memory/action/CalculateRetainedSizeAction.java index dd1612aee936..7afff98649d2 100644 --- a/java/debugger/impl/src/com/intellij/debugger/memory/action/CalculateRetainedSizeAction.java +++ b/java/debugger/impl/src/com/intellij/debugger/memory/action/CalculateRetainedSizeAction.java @@ -9,11 +9,13 @@ import com.intellij.debugger.engine.evaluation.EvaluateException; import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; import com.intellij.debugger.engine.events.SuspendContextCommandImpl; import com.intellij.debugger.memory.agent.MemoryAgent; +import com.intellij.debugger.memory.agent.MemoryAgentActionResult; import com.intellij.debugger.memory.agent.ui.RetainedSizeDialog; import com.intellij.notification.NotificationType; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.registry.Registry; import com.intellij.xdebugger.XDebuggerManager; import com.intellij.xdebugger.impl.XDebuggerManagerImpl; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; @@ -46,11 +48,19 @@ public class CalculateRetainedSizeAction extends DebuggerTreeAction { try { EvaluationContextImpl evaluationContext = new EvaluationContextImpl(suspendContext, suspendContext.getFrameProxy()); MemoryAgent memoryAgent = MemoryAgent.get(debugProcess); - Pair sizeAndHeldObjects = memoryAgent.estimateObjectSize(evaluationContext, reference); - dialog.setHeldObjectsAndRetainedSize( - Arrays.asList(sizeAndHeldObjects.getSecond()), - sizeAndHeldObjects.getFirst() + MemoryAgentActionResult> result = memoryAgent.estimateObjectSize( + evaluationContext, reference, Registry.get("debugger.memory.agent.action.timeout").asInteger() ); + if (result.executedSuccessfully()) { + Pair sizesAndHeldObjects = result.getResult(); + dialog.setHeldObjectsAndSizes( + Arrays.asList(sizesAndHeldObjects.getSecond()), + sizesAndHeldObjects.getFirst()[0], + sizesAndHeldObjects.getFirst()[1] + ); + } else { + dialog.setCalculationTimeout(); + } } catch (EvaluateException e) { XDebuggerManagerImpl.NOTIFICATION_GROUP.createNotification(JavaDebuggerBundle.message("action.failed"), NotificationType.ERROR); diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/agent/CalculationTimeoutReferringObject.java b/java/debugger/impl/src/com/intellij/debugger/memory/agent/CalculationTimeoutReferringObject.java new file mode 100644 index 000000000000..fe4192734e9b --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/memory/agent/CalculationTimeoutReferringObject.java @@ -0,0 +1,91 @@ +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.debugger.memory.agent; + +import com.intellij.debugger.DebuggerContext; +import com.intellij.debugger.JavaDebuggerBundle; +import com.intellij.debugger.engine.ReferringObject; +import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; +import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiExpression; +import com.intellij.xdebugger.frame.XFullValueEvaluator; +import com.intellij.xdebugger.frame.XValueNode; +import com.intellij.xdebugger.frame.presentation.XValuePresentation; +import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodePresentationConfigurator; +import com.sun.jdi.ObjectReference; +import com.sun.jdi.Value; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.util.function.Function; + +public class CalculationTimeoutReferringObject implements ReferringObject { + @NotNull + @Override + public ValueDescriptorImpl createValueDescription(@NotNull Project project, @NotNull Value referee) { + return new ValueDescriptorImpl(project, null) { + @NotNull + @Override + public String getName() { + return ""; + } + + @Nullable + @Override + public Value calcValue(EvaluationContextImpl evaluationContext) { + return null; + } + + @Nullable + @Override + public PsiExpression getDescriptorEvaluation(DebuggerContext context) { + return null; + } + }; + } + + @NotNull + @Override + public final Function getNodeCustomizer() { + return node -> new XValueNodePresentationConfigurator.ConfigurableXValueNodeImpl() { + @Override + public void applyPresentation(@Nullable Icon icon, @NotNull final XValuePresentation valuePresenter, boolean hasChildren) { + node.setPresentation(icon, new XValuePresentation() { + @NotNull + @Override + public String getSeparator() { + return ""; + } + + @Nullable + @Override + public String getType() { + return null; + } + + @Override + public void renderValue(@NotNull XValueTextRenderer renderer) { + renderer.renderValue(JavaDebuggerBundle.message("debugger.memory.agent.timeout.error")); + } + }, hasChildren); + } + + @Override + public void setFullValueEvaluator(@NotNull XFullValueEvaluator fullValueEvaluator) { + } + }; + } + + @Nullable + @Override + public String getNodeName(int order) { + return null; + } + + @Nullable + @Override + public ObjectReference getReference() { + return null; + } +} diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/agent/CompoundRootReferringObject.java b/java/debugger/impl/src/com/intellij/debugger/memory/agent/CompoundRootReferringObject.java new file mode 100644 index 000000000000..07013302f262 --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/memory/agent/CompoundRootReferringObject.java @@ -0,0 +1,97 @@ +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.debugger.memory.agent; + +import com.intellij.debugger.DebuggerContext; +import com.intellij.debugger.engine.ReferringObject; +import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; +import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl; +import com.intellij.icons.AllIcons; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiExpression; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.xdebugger.frame.XFullValueEvaluator; +import com.intellij.xdebugger.frame.XValueNode; +import com.intellij.xdebugger.frame.presentation.XValuePresentation; +import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodePresentationConfigurator; +import com.sun.jdi.ObjectReference; +import com.sun.jdi.Value; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.util.Arrays; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class CompoundRootReferringObject implements ReferringObject { + private final MemoryAgentReferenceKind[] myKinds; + + public CompoundRootReferringObject(MemoryAgentReferenceKind @NotNull[] kinds) { + myKinds = ContainerUtil.set(kinds).toArray(new MemoryAgentReferenceKind[0]); + } + + @NotNull + @Override + public ValueDescriptorImpl createValueDescription(@NotNull Project project, @NotNull Value referee) { + return new ValueDescriptorImpl(project, null) { + @Override + public String getName() { + return ""; + } + + @Override + public Value calcValue(EvaluationContextImpl evaluationContext) { + return null; + } + + @Override + public PsiExpression getDescriptorEvaluation(DebuggerContext context) { + return null; + } + }; + } + + @NotNull + @Override + public final Function getNodeCustomizer() { + return node -> new XValueNodePresentationConfigurator.ConfigurableXValueNodeImpl() { + @Override + public void applyPresentation(@Nullable Icon icon, @NotNull final XValuePresentation valuePresenter, boolean hasChildren) { + node.setPresentation(AllIcons.Nodes.Record, new XValuePresentation() { + @NotNull + @Override + public String getSeparator() { + return ": "; + } + + @Nullable + @Override + public String getType() { + return null; + } + + @Override + public void renderValue(@NotNull XValueTextRenderer renderer) { + renderer.renderValue(Arrays.stream(myKinds).map(kind -> kind.toString() + " reference").collect(Collectors.joining(", "))); + } + }, hasChildren); + } + + @Override + public void setFullValueEvaluator(@NotNull XFullValueEvaluator fullValueEvaluator) { + } + }; + } + + @NotNull + @Override + public String getNodeName(int order) { + return "Root"; + } + + @Nullable + @Override + public ObjectReference getReference() { + return null; + } +} diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/agent/GCRootReferringObject.java b/java/debugger/impl/src/com/intellij/debugger/memory/agent/GCRootReferringObject.java index eed9e2020ecc..826c5bfa4402 100644 --- a/java/debugger/impl/src/com/intellij/debugger/memory/agent/GCRootReferringObject.java +++ b/java/debugger/impl/src/com/intellij/debugger/memory/agent/GCRootReferringObject.java @@ -20,7 +20,7 @@ import javax.swing.*; import java.util.function.Function; public class GCRootReferringObject implements ReferringObject { - @NotNull private final MemoryAgentReferenceKind myKind; + private final MemoryAgentReferenceKind myKind; public GCRootReferringObject(@NotNull MemoryAgentReferenceKind kind) { this.myKind = kind; @@ -82,6 +82,11 @@ public class GCRootReferringObject implements ReferringObject { }; } + @NotNull + public MemoryAgentReferenceKind getKind() { + return myKind; + } + @NotNull @Override public String getNodeName(int order) { diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/agent/JNILocalReferringObject.java b/java/debugger/impl/src/com/intellij/debugger/memory/agent/JNILocalReferringObject.java new file mode 100644 index 000000000000..b273f6f01597 --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/memory/agent/JNILocalReferringObject.java @@ -0,0 +1,22 @@ +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.debugger.memory.agent; + +import org.jetbrains.annotations.NotNull; + +public class JNILocalReferringObject extends GCRootReferringObject { + private final long myTid; + private final long myDepth; + + public JNILocalReferringObject(@NotNull MemoryAgentReferenceKind kind, + long tid, long depth) { + super(kind); + this.myTid = tid; + this.myDepth = depth; + } + + @NotNull + @Override + protected String getAdditionalInfo() { + return String.format("TID: %d DEPTH: %d", myTid, myDepth); + } +} diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgent.java b/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgent.java index def4ed86d38a..28550aeeac2e 100644 --- a/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgent.java +++ b/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgent.java @@ -33,22 +33,34 @@ public interface MemoryAgent { @NotNull MemoryAgentCapabilities capabilities(); - Pair estimateObjectSize(@NotNull EvaluationContextImpl evaluationContext, @NotNull ObjectReference reference) throws EvaluateException; - - long[] estimateObjectsSizes(@NotNull EvaluationContextImpl evaluationContext, @NotNull List references) - throws EvaluateException; - - long[] getShallowSizeByClasses(@NotNull EvaluationContextImpl evaluationContext, @NotNull List classes) - throws EvaluateException; - - long[] getRetainedSizeByClasses(@NotNull EvaluationContextImpl evaluationContext, @NotNull List classes) - throws EvaluateException; - - Pair getShallowAndRetainedSizeByClasses(@NotNull EvaluationContextImpl evaluationContext, @NotNull List classes) - throws EvaluateException; + @NotNull + MemoryAgentActionResult> estimateObjectSize(@NotNull EvaluationContextImpl evaluationContext, + @NotNull ObjectReference reference, + long timeoutInMillis) throws EvaluateException; @NotNull - ReferringObjectsInfo findPathsToClosestGCRoots(@NotNull EvaluationContextImpl evaluationContext, @NotNull ObjectReference reference, - int pathsNumber, int objectsNumber) - throws EvaluateException; + MemoryAgentActionResult estimateObjectsSizes(@NotNull EvaluationContextImpl evaluationContext, + @NotNull List references, + long timeoutInMillis) throws EvaluateException; + + @NotNull + MemoryAgentActionResult getShallowSizeByClasses(@NotNull EvaluationContextImpl evaluationContext, + @NotNull List classes, + long timeoutInMillis) throws EvaluateException; + + @NotNull + MemoryAgentActionResult getRetainedSizeByClasses(@NotNull EvaluationContextImpl evaluationContext, + @NotNull List classes, + long timeoutInMillis) throws EvaluateException; + + @NotNull + MemoryAgentActionResult> getShallowAndRetainedSizeByClasses(@NotNull EvaluationContextImpl evaluationContext, + @NotNull List classes, + long timeoutInMillis) throws EvaluateException; + + @NotNull + MemoryAgentActionResult findPathsToClosestGCRoots(@NotNull EvaluationContextImpl evaluationContext, + @NotNull ObjectReference reference, + int pathsNumber, int objectsNumber, + long timeoutInMillis) throws EvaluateException; } diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgentActionResult.java b/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgentActionResult.java new file mode 100644 index 000000000000..2a92c1d0e65a --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgentActionResult.java @@ -0,0 +1,32 @@ +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.debugger.memory.agent; + +import org.jetbrains.annotations.NotNull; + +public class MemoryAgentActionResult { + public enum ErrorCode { + OK, + TIMEOUT; + + public static ErrorCode valueOf(int value) { + return value == 0 ? OK : TIMEOUT; + } + } + + private final ErrorCode myErrorCode; + private final T myResult; + + public MemoryAgentActionResult(@NotNull T result, @NotNull ErrorCode errorCode) { + myErrorCode = errorCode; + myResult = result; + } + + @NotNull + public T getResult() { + return myResult; + } + + public boolean executedSuccessfully() { + return myErrorCode != ErrorCode.TIMEOUT; + } +} diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgentImpl.java b/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgentImpl.java index 548aa640e1c8..7a73fac597c3 100644 --- a/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgentImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgentImpl.java @@ -4,6 +4,7 @@ package com.intellij.debugger.memory.agent; import com.intellij.debugger.engine.evaluation.EvaluateException; import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.registry.Registry; import com.sun.jdi.ObjectReference; import com.sun.jdi.ReferenceType; import org.jetbrains.annotations.NotNull; @@ -18,64 +19,78 @@ class MemoryAgentImpl implements MemoryAgent { myCapabilities = capabilities; } + @NotNull @Override - public Pair estimateObjectSize(@NotNull EvaluationContextImpl evaluationContext, @NotNull ObjectReference reference) - throws EvaluateException { + public MemoryAgentActionResult> estimateObjectSize(@NotNull EvaluationContextImpl evaluationContext, + @NotNull ObjectReference reference, + long timeoutInMillis) throws EvaluateException { if (!myCapabilities.canEstimateObjectSize()) { throw new UnsupportedOperationException("Memory agent can't estimate object size"); } - return MemoryAgentOperations.estimateObjectSize(evaluationContext, reference); + + return MemoryAgentOperations.estimateObjectSize(evaluationContext, reference, timeoutInMillis); } + @NotNull @Override - public long[] estimateObjectsSizes(@NotNull EvaluationContextImpl evaluationContext, @NotNull List references) - throws EvaluateException { + public MemoryAgentActionResult estimateObjectsSizes(@NotNull EvaluationContextImpl evaluationContext, + @NotNull List references, + long timeoutInMillis) throws EvaluateException { if (!myCapabilities.canEstimateObjectsSizes()) { throw new UnsupportedOperationException("Memory agent can't estimate objects sizes"); } - return MemoryAgentOperations.estimateObjectsSizes(evaluationContext, references); + return MemoryAgentOperations.estimateObjectsSizes(evaluationContext, references, timeoutInMillis); } + @NotNull @Override - public long[] getShallowSizeByClasses(@NotNull EvaluationContextImpl evaluationContext, @NotNull List classes) - throws EvaluateException { + public MemoryAgentActionResult getShallowSizeByClasses(@NotNull EvaluationContextImpl evaluationContext, + @NotNull List classes, + long timeoutInMillis) throws EvaluateException { if (!myCapabilities.canGetShallowSizeByClasses()) { throw new UnsupportedOperationException("Memory agent can't get shallow size by classes"); } - return MemoryAgentOperations.getShallowSizeByClasses(evaluationContext, classes); + return MemoryAgentOperations.getShallowSizeByClasses(evaluationContext, classes, timeoutInMillis); } + @NotNull @Override - public long[] getRetainedSizeByClasses(@NotNull EvaluationContextImpl evaluationContext, @NotNull List classes) - throws EvaluateException { + public MemoryAgentActionResult getRetainedSizeByClasses(@NotNull EvaluationContextImpl evaluationContext, + @NotNull List classes, + long timeoutInMillis) throws EvaluateException { if (!myCapabilities.canGetRetainedSizeByClasses()) { throw new UnsupportedOperationException("Memory agent can't get retained size by classes"); } - return MemoryAgentOperations.getRetainedSizeByClasses(evaluationContext, classes); + return MemoryAgentOperations.getRetainedSizeByClasses(evaluationContext, classes, timeoutInMillis); } + @NotNull @Override - public Pair getShallowAndRetainedSizeByClasses(@NotNull EvaluationContextImpl evaluationContext, @NotNull List classes) - throws EvaluateException { + public MemoryAgentActionResult> getShallowAndRetainedSizeByClasses(@NotNull EvaluationContextImpl evaluationContext, + @NotNull List classes, + long timeoutInMillis) throws EvaluateException { if (!myCapabilities.canGetRetainedSizeByClasses() || !myCapabilities.canGetShallowSizeByClasses()) { throw new UnsupportedOperationException("Memory agent can't get shallow and retained size by classes"); } - return MemoryAgentOperations.getShallowAndRetainedSizeByClasses(evaluationContext, classes); + return MemoryAgentOperations.getShallowAndRetainedSizeByClasses(evaluationContext, classes, timeoutInMillis); } + @NotNull @Override - public @NotNull ReferringObjectsInfo findPathsToClosestGCRoots(@NotNull EvaluationContextImpl evaluationContext, - @NotNull ObjectReference reference, - int pathsNumber, int objectsNumber) throws EvaluateException { + public MemoryAgentActionResult findPathsToClosestGCRoots(@NotNull EvaluationContextImpl evaluationContext, + @NotNull ObjectReference reference, + int pathsNumber, + int objectsNumber, + long timeoutInMillis) throws EvaluateException { if (!myCapabilities.canFindPathsToClosestGcRoots()) { throw new UnsupportedOperationException("Memory agent can't provide paths to closest gc roots"); } - return MemoryAgentOperations.findPathsToClosestGCRoots(evaluationContext, reference, pathsNumber, objectsNumber); + return MemoryAgentOperations.findPathsToClosestGCRoots(evaluationContext, reference, pathsNumber, objectsNumber, timeoutInMillis); } @NotNull diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgentOperations.java b/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgentOperations.java index b45960159d4c..20a28488270b 100644 --- a/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgentOperations.java +++ b/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgentOperations.java @@ -26,57 +26,120 @@ final class MemoryAgentOperations { private static final Key MEMORY_AGENT_KEY = Key.create("MEMORY_AGENT_KEY"); private static final Logger LOG = Logger.getInstance(MemoryAgentOperations.class); - @NotNull - static Pair estimateObjectSize(@NotNull EvaluationContextImpl evaluationContext, @NotNull ObjectReference reference) - throws EvaluateException { - Value result = callMethod(evaluationContext, MemoryAgentNames.Methods.ESTIMATE_OBJECT_SIZE, Collections.singletonList(reference)); - Pair> pair = SizeAndHeldObjectsParser.INSTANCE.parse(result); - return new Pair<>(pair.getFirst(), pair.getSecond().toArray(new ObjectReference[0])); + private static LongValue getTimeoutValue(@NotNull EvaluationContextImpl evaluationContext, long timeoutInMillis) { + return evaluationContext.getDebugProcess().getVirtualMachineProxy().mirrorOf(timeoutInMillis); } - static long @NotNull [] estimateObjectsSizes(@NotNull EvaluationContextImpl evaluationContext, @NotNull List references) - throws EvaluateException { + @NotNull + static MemoryAgentActionResult> estimateObjectSize(@NotNull EvaluationContextImpl evaluationContext, + @NotNull ObjectReference reference, + long timeoutInMillis) throws EvaluateException { + LongValue timeoutValue = getTimeoutValue(evaluationContext, timeoutInMillis); + Value result = callMethod(evaluationContext, MemoryAgentNames.Methods.ESTIMATE_OBJECT_SIZE, Arrays.asList(reference, timeoutValue)); + Pair errCodeAndResult = ErrorCodeParser.INSTANCE.parse(result); + MemoryAgentActionResult.ErrorCode errCode = errCodeAndResult.getFirst(); + Pair sizesAndObjects; + if (errCode != MemoryAgentActionResult.ErrorCode.OK) { + sizesAndObjects = new Pair<>(new long[0], new ObjectReference[0]); + } else { + Pair parsingResult = SizeAndHeldObjectsParser.INSTANCE.parse(errCodeAndResult.getSecond()); + sizesAndObjects = new Pair<>( + Arrays.stream(parsingResult.getFirst()).mapToLong(Long::longValue).toArray(), + parsingResult.getSecond() + ); + } + + return new MemoryAgentActionResult<>(sizesAndObjects, errCode); + } + + @NotNull + static MemoryAgentActionResult estimateObjectsSizes(@NotNull EvaluationContextImpl evaluationContext, + @NotNull List references, + long timeoutInMillis) throws EvaluateException { + LongValue timeoutValue = getTimeoutValue(evaluationContext, timeoutInMillis); ArrayReference array = wrapWithArray(evaluationContext, references); - Value result = callMethod(evaluationContext, MemoryAgentNames.Methods.ESTIMATE_OBJECTS_SIZE, Collections.singletonList(array)); - return LongArrayParser.INSTANCE.parse(result).stream().mapToLong(Long::longValue).toArray(); - } - - static long @NotNull [] getShallowSizeByClasses(@NotNull EvaluationContextImpl evaluationContext, @NotNull List classes) - throws EvaluateException { - ArrayReference array = wrapWithArray(evaluationContext, ContainerUtil.map(classes, ReferenceType::classObject)); - Value result = callMethod(evaluationContext, MemoryAgentNames.Methods.GET_SHALLOW_SIZE_BY_CLASSES, Collections.singletonList(array)); - return LongArrayParser.INSTANCE.parse(result).stream().mapToLong(Long::longValue).toArray(); - } - - static long @NotNull [] getRetainedSizeByClasses(@NotNull EvaluationContextImpl evaluationContext, @NotNull List classes) - throws EvaluateException { - ArrayReference array = wrapWithArray(evaluationContext, ContainerUtil.map(classes, ReferenceType::classObject)); - Value result = callMethod(evaluationContext, MemoryAgentNames.Methods.GET_RETAINED_SIZE_BY_CLASSES, Collections.singletonList(array)); - return LongArrayParser.INSTANCE.parse(result).stream().mapToLong(Long::longValue).toArray(); + Value result = callMethod(evaluationContext, MemoryAgentNames.Methods.ESTIMATE_OBJECTS_SIZE, Arrays.asList(array, timeoutValue)); + Pair errCodeAndResult = ErrorCodeParser.INSTANCE.parse(result); + return new MemoryAgentActionResult<>( + LongArrayParser.INSTANCE.parse(errCodeAndResult.getSecond()).stream().mapToLong(Long::longValue).toArray(), + errCodeAndResult.getFirst() + ); } @NotNull - static Pair getShallowAndRetainedSizeByClasses(@NotNull EvaluationContextImpl evaluationContext, @NotNull List classes) - throws EvaluateException { + static MemoryAgentActionResult getShallowSizeByClasses(@NotNull EvaluationContextImpl evaluationContext, + @NotNull List classes, + long timeoutInMillis) throws EvaluateException { + LongValue timeoutValue = getTimeoutValue(evaluationContext, timeoutInMillis); ArrayReference array = wrapWithArray(evaluationContext, ContainerUtil.map(classes, ReferenceType::classObject)); - Value result = callMethod(evaluationContext, MemoryAgentNames.Methods.GET_SHALLOW_AND_RETAINED_SIZE_BY_CLASSES, Collections.singletonList(array)); - Pair, List> pair = ShallowAndRetainedSizeParser.INSTANCE.parse(result); - return new Pair<>(pair.getFirst().stream().mapToLong(Long::longValue).toArray(), - pair.getSecond().stream().mapToLong(Long::longValue).toArray()); + Value result = callMethod(evaluationContext, MemoryAgentNames.Methods.GET_SHALLOW_SIZE_BY_CLASSES, Arrays.asList(array, timeoutValue)); + Pair errCodeAndResult = ErrorCodeParser.INSTANCE.parse(result); + return new MemoryAgentActionResult<>( + LongArrayParser.INSTANCE.parse(errCodeAndResult.getSecond()).stream().mapToLong(Long::longValue).toArray(), + errCodeAndResult.getFirst() + ); } @NotNull - static ReferringObjectsInfo findPathsToClosestGCRoots(@NotNull EvaluationContextImpl evaluationContext, - @NotNull ObjectReference reference, int pathsNumber, - int objectsNumber) throws EvaluateException { + static MemoryAgentActionResult getRetainedSizeByClasses(@NotNull EvaluationContextImpl evaluationContext, + @NotNull List classes, + long timeoutInMillis) throws EvaluateException { + LongValue timeoutValue = getTimeoutValue(evaluationContext, timeoutInMillis); + ArrayReference array = wrapWithArray(evaluationContext, ContainerUtil.map(classes, ReferenceType::classObject)); + Value result = callMethod(evaluationContext, MemoryAgentNames.Methods.GET_RETAINED_SIZE_BY_CLASSES, Arrays.asList(array, timeoutValue)); + Pair errCodeAndResult = ErrorCodeParser.INSTANCE.parse(result); + return new MemoryAgentActionResult<>( + LongArrayParser.INSTANCE.parse(errCodeAndResult.getSecond()).stream().mapToLong(Long::longValue).toArray(), + errCodeAndResult.getFirst() + ); + } + + @NotNull + static MemoryAgentActionResult> getShallowAndRetainedSizeByClasses(@NotNull EvaluationContextImpl evaluationContext, + @NotNull List classes, + long timeoutInMillis) throws EvaluateException { + LongValue timeoutValue = getTimeoutValue(evaluationContext, timeoutInMillis); + ArrayReference array = wrapWithArray(evaluationContext, ContainerUtil.map(classes, ReferenceType::classObject)); + Value result = callMethod(evaluationContext, MemoryAgentNames.Methods.GET_SHALLOW_AND_RETAINED_SIZE_BY_CLASSES, Arrays.asList(array, timeoutValue)); + Pair errCodeAndResult = ErrorCodeParser.INSTANCE.parse(result); + Pair, List> shallowAndRetainedSizes = ShallowAndRetainedSizeParser.INSTANCE.parse(errCodeAndResult.getSecond()); + return new MemoryAgentActionResult<>( + new Pair<>( + shallowAndRetainedSizes.getFirst().stream().mapToLong(Long::longValue).toArray(), + shallowAndRetainedSizes.getSecond().stream().mapToLong(Long::longValue).toArray() + ), + errCodeAndResult.getFirst() + ); + } + + @NotNull + static MemoryAgentActionResult findPathsToClosestGCRoots(@NotNull EvaluationContextImpl evaluationContext, + @NotNull ObjectReference reference, int pathsNumber, + int objectsNumber, long timeoutInMillis) throws EvaluateException { + LongValue timeoutValue = getTimeoutValue(evaluationContext, timeoutInMillis); IntegerValue pathsNumberValue = evaluationContext.getDebugProcess().getVirtualMachineProxy().mirrorOf(pathsNumber); IntegerValue objectsNumberValue = evaluationContext.getDebugProcess().getVirtualMachineProxy().mirrorOf(objectsNumber); - Value value = callMethod( + Value result = callMethod( evaluationContext, MemoryAgentNames.Methods.FIND_PATHS_TO_CLOSEST_GC_ROOTS, - Arrays.asList(reference, pathsNumberValue, objectsNumberValue) + Arrays.asList(reference, pathsNumberValue, objectsNumberValue, timeoutValue) ); - return GcRootsPathsParser.INSTANCE.parse(value); + + Pair errCodeAndResult = ErrorCodeParser.INSTANCE.parse(result); + MemoryAgentActionResult.ErrorCode errCode = errCodeAndResult.getFirst(); + ReferringObjectsInfo returnValue; + if (errCode != MemoryAgentActionResult.ErrorCode.OK) { + returnValue = new ReferringObjectsInfo( + Collections.singletonList(reference), + Collections.singletonList( + Collections.singletonList(new CalculationTimeoutReferringObject()) + ) + ); + } else { + returnValue = GcRootsPathsParser.INSTANCE.parse(errCodeAndResult.getSecond()); + } + + return new MemoryAgentActionResult<>(returnValue, errCodeAndResult.getFirst()); } @NotNull diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgentPathsToClosestGCRootsProvider.java b/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgentPathsToClosestGCRootsProvider.java index 1c43a0a69208..47a515e02d56 100644 --- a/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgentPathsToClosestGCRootsProvider.java +++ b/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgentPathsToClosestGCRootsProvider.java @@ -5,6 +5,7 @@ import com.intellij.debugger.engine.ReferringObject; import com.intellij.debugger.engine.ReferringObjectsProvider; import com.intellij.debugger.engine.evaluation.EvaluateException; import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; +import com.intellij.openapi.util.registry.Registry; import com.sun.jdi.ObjectReference; import org.jetbrains.annotations.NotNull; @@ -49,6 +50,9 @@ public class MemoryAgentPathsToClosestGCRootsProvider implements ReferringObject throw new UnsupportedOperationException(); } - return memoryAgent.findPathsToClosestGCRoots(evaluationContext, value, myPathsToRequestLimit, myObjectsToRequestLimit); + MemoryAgentActionResult result = memoryAgent.findPathsToClosestGCRoots( + evaluationContext, value, myPathsToRequestLimit, myObjectsToRequestLimit, Registry.get("debugger.memory.agent.action.timeout").asInteger() + ); + return result.getResult(); } } diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgentUtil.java b/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgentUtil.java index d44747ca1b28..ac43be566054 100644 --- a/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgentUtil.java +++ b/java/debugger/impl/src/com/intellij/debugger/memory/agent/MemoryAgentUtil.java @@ -137,7 +137,11 @@ public final class MemoryAgentUtil { return objects; } try { - long[] sizes = agent.estimateObjectsSizes(context, ContainerUtil.map(objects, x -> x.getObjectReference())); + long[] sizes = agent.estimateObjectsSizes( + context, + ContainerUtil.map(objects, x -> x.getObjectReference()), + Registry.get("debugger.memory.agent.action.timeout").asInteger() + ).getResult(); return IntStreamEx.range(0, objects.size()) .mapToObj(i -> new SizedReferenceInfo(objects.get(i).getObjectReference(), sizes[i])) .reverseSorted(Comparator.comparing(x -> x.size())) @@ -194,7 +198,7 @@ public final class MemoryAgentUtil { } return ApplicationManager.getApplication() - .executeOnPooledThread(() -> new AgentExtractor().extract(detectAgentKind(jdkPath), getAgentDirectory())) + .executeOnPooledThread(() -> AgentExtractor.INSTANCE.extract(detectAgentKind(jdkPath), getAgentDirectory())) .get(1, TimeUnit.SECONDS); } diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/agent/StackLocalReferringObject.java b/java/debugger/impl/src/com/intellij/debugger/memory/agent/StackLocalReferringObject.java index 7b178c305f47..cf56349e9906 100644 --- a/java/debugger/impl/src/com/intellij/debugger/memory/agent/StackLocalReferringObject.java +++ b/java/debugger/impl/src/com/intellij/debugger/memory/agent/StackLocalReferringObject.java @@ -9,7 +9,7 @@ public class StackLocalReferringObject extends GCRootReferringObject { private final String myMethodName; public StackLocalReferringObject(@NotNull MemoryAgentReferenceKind kind, - String methodName, + @NotNull String methodName, long tid, long depth) { super(kind); this.myTid = tid; @@ -20,8 +20,6 @@ public class StackLocalReferringObject extends GCRootReferringObject { @NotNull @Override protected String getAdditionalInfo() { - return String.format("%sTID: %d DEPTH: %d", - myMethodName != null ? String.format("from method: \"%s\" ", myMethodName) : "", - myTid, myDepth); + return String.format("in method: \"%s\" TID: %d DEPTH: %d", myMethodName, myTid, myDepth); } } diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/agent/parsers/Parsers.kt b/java/debugger/impl/src/com/intellij/debugger/memory/agent/parsers/Parsers.kt index 257f1915d33c..0674a0e475f4 100644 --- a/java/debugger/impl/src/com/intellij/debugger/memory/agent/parsers/Parsers.kt +++ b/java/debugger/impl/src/com/intellij/debugger/memory/agent/parsers/Parsers.kt @@ -5,6 +5,8 @@ import com.intellij.debugger.engine.ReferringObject import com.intellij.debugger.memory.agent.* import com.intellij.openapi.util.Pair import com.sun.jdi.* +import java.util.* +import kotlin.collections.ArrayList object StringParser : ResultParser { override fun parse(value: Value): String { @@ -85,15 +87,11 @@ object ObjectsReferencesInfoParser : ResultParser { throw UnexpectedValueFormatException("Object references information should be represented by array") val distinctIndices = mutableSetOf() - val referenceInfos = mutableListOf() + val referenceInfos = LinkedList() + val rootReferenceKinds = mutableListOf() for ((i, index) in indices.withIndex()) { if (index == -1) { - referenceInfos.add( - MemoryAgentReferringObjectCreator.createRootReferringObject( - MemoryAgentReferenceKind.valueOf(kinds[i]), - infos.getValue(i) - ) - ) + rootReferenceKinds.add(MemoryAgentReferenceKind.valueOf(kinds[i])) } else if (!distinctIndices.contains(index)) { distinctIndices.add(index) referenceInfos.add( @@ -107,6 +105,9 @@ object ObjectsReferencesInfoParser : ResultParser { } } + if (rootReferenceKinds.isNotEmpty()) { + referenceInfos.add(0, CompoundRootReferringObject(rootReferenceKinds.toTypedArray())) + } result.add(referenceInfos) } @@ -142,13 +143,25 @@ object ShallowAndRetainedSizeParser : ResultParser, List>> } } -object SizeAndHeldObjectsParser : ResultParser>> { - override fun parse(value: Value): Pair> { +object SizeAndHeldObjectsParser : ResultParser, Array>> { + override fun parse(value: Value): Pair, Array> { if (value !is ArrayReference) throw UnexpectedValueFormatException("Array expected") if (value.length() < 2) throw UnexpectedValueFormatException("long and array of objects expected") return Pair( - LongArrayParser.parse(value.getValue(0))[0], - ObjectReferencesParser.parse(value.getValue(1)) + LongArrayParser.parse(value.getValue(0)).toTypedArray(), + ObjectReferencesParser.parse(value.getValue(1)).toTypedArray() + ) + } +} + +object ErrorCodeParser : ResultParser> { + override fun parse(value: Value): Pair { + if (value !is ArrayReference) throw UnexpectedValueFormatException("Array expected") + return Pair( + MemoryAgentActionResult.ErrorCode.valueOf( + IntArrayParser.parse(value.getValue(0))[0] + ), + value.getValue(1) ) } } @@ -173,12 +186,16 @@ object MemoryAgentReferringObjectCreator { value: Value?): GCRootReferringObject { return if (value == null) GCRootReferringObject(kind) else when (kind) { - MemoryAgentReferenceKind.STACK_LOCAL, + MemoryAgentReferenceKind.STACK_LOCAL -> { + if (value !is ArrayReference) return GCRootReferringObject(kind) + val methodName = StringArrayParser.parse(value.getValue(1))[0] ?: return GCRootReferringObject(kind) + val longs = LongArrayParser.parse(value.getValue(0)) + StackLocalReferringObject(kind, methodName, longs[0], longs[1]) + } MemoryAgentReferenceKind.JNI_LOCAL -> { if (value !is ArrayReference) return GCRootReferringObject(kind) val longs = LongArrayParser.parse(value.getValue(0)) - val methodName = value.getValue(1)?.let { StringArrayParser.parse(it)[0] } - StackLocalReferringObject(kind, methodName, longs[0], longs[1]) + JNILocalReferringObject(kind, longs[0], longs[1]) } else -> GCRootReferringObject(kind) } diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/agent/ui/RetainedSizeDialog.java b/java/debugger/impl/src/com/intellij/debugger/memory/agent/ui/RetainedSizeDialog.java index ff7d0d3af4d2..9731145a5f1f 100644 --- a/java/debugger/impl/src/com/intellij/debugger/memory/agent/ui/RetainedSizeDialog.java +++ b/java/debugger/impl/src/com/intellij/debugger/memory/agent/ui/RetainedSizeDialog.java @@ -55,7 +55,7 @@ public class RetainedSizeDialog extends DialogWrapper { private final BorderLayoutPanel myPanel; private final NodeHighlighter myHighlighter; private final String myRootName; - private final JBLabel myRetainedSizeLabel; + private JBLabel myRetainedSizeLabel; public RetainedSizeDialog(@NotNull Project project, XDebuggerEditorsProvider editorsProvider, @@ -78,20 +78,9 @@ public class RetainedSizeDialog extends DialogWrapper { myHeldObjects = new HashSet<>(); myRootName = name; - JBPanel topPanel = new JBPanel<>(); - topPanel.setLayout(new VerticalFlowLayout()); - myRetainedSizeLabel = new JBLabel(JavaDebuggerBundle.message("action.calculate.retained.size.waiting.message")); - topPanel.add(myRetainedSizeLabel); - topPanel.add( - new JBLabel( - JavaDebuggerBundle.message("action.calculate.retained.size.info", myRootName), - AllIcons.General.Information, - SwingConstants.LEFT - ) - ); myPanel = JBUI.Panels.simplePanel() .addToCenter(ScrollPaneFactory.createScrollPane(myTree)) - .addToTop(topPanel); + .addToTop(createTopPanel()); if (session != null) { session.addSessionListener(new XDebugSessionListener() { @@ -112,7 +101,11 @@ public class RetainedSizeDialog extends DialogWrapper { init(); } - public void setHeldObjectsAndRetainedSize(@NotNull Collection heldObjects, long retainedSize) { + public void setCalculationTimeout() { + myRetainedSizeLabel.setText(JavaDebuggerBundle.message("debugger.memory.agent.timeout.error")); + } + + public void setHeldObjectsAndSizes(@NotNull Collection heldObjects, long shallowSize, long retainedSize) { myHeldObjects.clear(); myHeldObjects.addAll(heldObjects); highlightLoadedChildren(); @@ -120,6 +113,7 @@ public class RetainedSizeDialog extends DialogWrapper { JavaDebuggerBundle.message( "action.calculate.retained.size.text", myRootName, + StringUtil.formatFileSize(shallowSize), StringUtil.formatFileSize(retainedSize) ) ); @@ -175,6 +169,22 @@ public class RetainedSizeDialog extends DialogWrapper { } } + @NotNull + private JBPanel createTopPanel() { + JBPanel panel = new JBPanel<>(); + panel.setLayout(new VerticalFlowLayout()); + myRetainedSizeLabel = new JBLabel(JavaDebuggerBundle.message("action.calculate.retained.size.waiting.message")); + panel.add(myRetainedSizeLabel); + panel.add( + new JBLabel( + JavaDebuggerBundle.message("action.calculate.retained.size.info", myRootName), + AllIcons.General.Information, + SwingConstants.LEFT + ) + ); + return panel; + } + private class NodeHighlighter implements XDebuggerTreeListener { private boolean mySkipNotification; private final Map myCachedIcons; @@ -188,10 +198,9 @@ public class RetainedSizeDialog extends DialogWrapper { public void nodeLoaded(@NotNull RestorableStateNode node, @NotNull String name) { if (!mySkipNotification && node instanceof XValueNodeImpl) { XValueNodeImpl nodeImpl = (XValueNodeImpl)node; - if (myHeldObjects.contains(getObjectReference(nodeImpl))) { + if (nodeImpl != nodeImpl.getTree().getRoot() && myHeldObjects.contains(getObjectReference(nodeImpl))) { XValuePresentation presentation = nodeImpl.getValuePresentation(); - Icon icon = nodeImpl.getIcon(); - if (presentation != null && icon != PlatformDebuggerImplIcons.PinToTop.UnpinnedItem) { + if (presentation != null && nodeImpl.getIcon() != PlatformDebuggerImplIcons.PinToTop.UnpinnedItem) { highlightNode(nodeImpl); } } diff --git a/java/debugger/memory-agent/src/com/intellij/debugger/memory/agent/extractor/AgentExtractor.kt b/java/debugger/memory-agent/src/com/intellij/debugger/memory/agent/extractor/AgentExtractor.kt index a423d538b0f5..9dff1f1239a7 100644 --- a/java/debugger/memory-agent/src/com/intellij/debugger/memory/agent/extractor/AgentExtractor.kt +++ b/java/debugger/memory-agent/src/com/intellij/debugger/memory/agent/extractor/AgentExtractor.kt @@ -3,23 +3,31 @@ package com.intellij.debugger.memory.agent.extractor import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtilRt +import java.io.File import java.io.FileNotFoundException import java.nio.file.Files import java.nio.file.Path -class AgentExtractor { +object AgentExtractor { + private lateinit var extractedFile: File + private var lastModified = -1L + + @Synchronized fun extract(agentType: AgentLibraryType, directory: Path): Path { - Files.createDirectories(directory) - Files.createTempFile(directory, "${agentType.prefix}memory_agent", agentType.suffix) - val file = FileUtilRt.createTempFile(directory.toFile(), "${agentType.prefix}memory_agent", agentType.suffix, true).toPath() - val agentFileName = "${agentType.prefix}memory_agent${agentType.suffix}" - val inputStream = AgentExtractor::class.java.classLoader.getResourceAsStream("bin/$agentFileName") ?: throw FileNotFoundException(agentFileName) - inputStream.use { input -> - Files.newOutputStream(file).use { output -> - FileUtil.copy(input, output) - } + if (!::extractedFile.isInitialized || !extractedFile.exists() || extractedFile.lastModified() != lastModified) { + val agentFileName = "${agentType.prefix}memory_agent${agentType.suffix}" + val file = FileUtilRt.createTempFile(directory.toFile(), "${agentType.prefix}memory_agent", agentType.suffix, true) + val inputStream = AgentExtractor::class.java.classLoader.getResourceAsStream("bin/$agentFileName") ?: throw FileNotFoundException(agentFileName) + inputStream.use { input -> + Files.newOutputStream(file.toPath()).use { output -> + FileUtil.copy(input, output) + } + } + extractedFile = file + lastModified = file.lastModified() } - return file + + return extractedFile.toPath() } enum class AgentLibraryType(val prefix: String, val suffix: String) { diff --git a/java/debugger/openapi/resources/messages/JavaDebuggerBundle.properties b/java/debugger/openapi/resources/messages/JavaDebuggerBundle.properties index db8e8f79b4f1..1af5c85f9ae8 100644 --- a/java/debugger/openapi/resources/messages/JavaDebuggerBundle.properties +++ b/java/debugger/openapi/resources/messages/JavaDebuggerBundle.properties @@ -401,7 +401,7 @@ action.watch.method.return.value.description=Enables watching last executed meth action.watches.method.return.value.enable=Show Method Return Values action.calculate.retained.size.info=Retained objects of ''{0}'' are highlighted action.calculate.retained.size.title=Retained Size of ''{0}'' -action.calculate.retained.size.text=Retained size of ''{0}'' is {1} +action.calculate.retained.size.text=Shallow size of ''{0}'' is {1}, retained size is {2} action.calculate.retained.size.waiting.message=Calculating retained size... action.watches.method.return.value.unavailable.reason=Feature is not supported by the target VM action.auto.variables.mode=Auto-Variables Mode @@ -513,3 +513,4 @@ array.filter.node.clear.link=\ clear breakpoint.variant.text.line=Line debugger.attach.group.name.java=Java debugger.attach.group.name.java.read.only=Java Read Only +debugger.memory.agent.timeout.error=Calculation timeout (heap is too large and memory agent can't execute this operation in reasonable time, it's preferable to capture the heap dump) \ No newline at end of file diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index badef26b60bc..9667fa6c377c 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -2334,6 +2334,8 @@ group.Patch.MainMenu.text=Patch action.LoadUnloadModules.text=Load/Unload Modules... group.UsageGroupingActionGroup.text=Usage View Grouping group.ArrangementRulesGroup.text=Arrangement Rules +group.UsageGroupingActionGroup.text=Usage View Grouping +group.ArrangementRulesGroup.text=Arrangement Rules group.FileChooserToolbar.text=File Chooser action.EditorTranspose.text=Transpose diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index ba4d24568a1d..5e6f1ab07c9e 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -449,6 +449,8 @@ debugger.enable.overhead.monitor=true debugger.memory.agent.debug=false debugger.memory.agent.debug.description=Enable debug logging to stdout from memory agent debugger.memory.agent.debug.path= +debugger.memory.agent.action.timeout=10000 +debugger.memory.agent.action.timeout.description=Set debugger memory agent action timeout in millis debugger.memory.agent.debug.path.description=Force debugger to use specified memory agent library instead of bundled one (only for debugging purpose). Will be used only if debugger.memory.agent.debug checked debugger.memory.agent.use.in.memory.view=false debugger.memory.agent.use.in.memory.view.description=Use memory agent to estimate retained sizes in the Instances Window