[memory-agent] Add retained sizes into for objects in instances tree if memory agent enabled

This commit is contained in:
Vitaliy.Bibaev
2019-02-06 19:47:22 +03:00
parent 27263006d3
commit df16183fee
6 changed files with 95 additions and 29 deletions
@@ -4,19 +4,26 @@ package com.intellij.debugger.memory.agent;
import com.intellij.debugger.engine.DebugProcessAdapterImpl;
import com.intellij.debugger.engine.DebugProcessImpl;
import com.intellij.debugger.engine.SuspendContextImpl;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.jdi.StackFrameProxyImpl;
import com.intellij.debugger.memory.agent.extractor.AgentExtractor;
import com.intellij.debugger.memory.ui.JavaReferenceInfo;
import com.intellij.debugger.memory.ui.SizedReferenceInfo;
import com.intellij.execution.JavaExecutionUtil;
import com.intellij.execution.configurations.JavaParameters;
import com.intellij.execution.configurations.ParametersList;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.util.containers.ContainerUtil;
import one.util.streamex.IntStreamEx;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -64,6 +71,23 @@ public class MemoryAgentUtil {
parametersList.add("-agentpath:" + path);
}
public static List<JavaReferenceInfo> tryCalculateSizes(@NotNull List<JavaReferenceInfo> objects, @Nullable MemoryAgent agent) {
if (agent == null || !agent.canEvaluateObjectsSizes()) return objects;
try {
long[] sizes = agent.evaluateObjectsSizes(ContainerUtil.map(objects, x -> x.getObjectReference()));
return IntStreamEx.range(0, objects.size())
.mapToObj(i -> new SizedReferenceInfo(objects.get(i).getObjectReference(), sizes[i]))
.reverseSorted(Comparator.comparing(x -> x.size()))
.map(x -> (JavaReferenceInfo)x)
.toList();
}
catch (EvaluateException e) {
LOG.error("Could not estimate objects sizes");
}
return objects;
}
public static void loadAgentProxy(@NotNull DebugProcessImpl debugProcess, @NotNull Consumer<MemoryAgent> agentLoaded) {
debugProcess.addDebugProcessListener(new DebugProcessAdapterImpl() {
@Override
@@ -16,9 +16,9 @@
package com.intellij.debugger.memory.filtering;
import com.intellij.debugger.engine.DebugProcessImpl;
import com.intellij.debugger.memory.ui.JavaReferenceInfo;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.xdebugger.XExpression;
import com.sun.jdi.Value;
import org.jetbrains.annotations.NotNull;
/**
@@ -54,18 +54,18 @@ public class FilteringTask implements Runnable {
myCallback.started(myValues.size());
int proceedCount;
for (proceedCount = 0; proceedCount < myValues.size() && !myIsCancelled; proceedCount++) {
Value value = myValues.get(proceedCount);
CheckingResult result = myChecker.check(value);
JavaReferenceInfo info = myValues.get(proceedCount);
CheckingResult result = myChecker.check(info.getObjectReference());
FilteringTaskCallback.Action action = FilteringTaskCallback.Action.CONTINUE;
switch (result.getResult()) {
case MATCH:
action = myCallback.matched(value);
action = myCallback.matched(info);
break;
case NO_MATCH:
action = myCallback.notMatched(value);
action = myCallback.notMatched(info);
break;
case ERROR:
action = myCallback.error(value, result.getFailureDescription());
action = myCallback.error(info, result.getFailureDescription());
break;
}
@@ -85,6 +85,7 @@ public class FilteringTask implements Runnable {
public interface ValuesList {
int size();
Value get(int index);
JavaReferenceInfo get(int index);
}
}
@@ -15,7 +15,7 @@
*/
package com.intellij.debugger.memory.filtering;
import com.sun.jdi.Value;
import com.intellij.debugger.memory.ui.JavaReferenceInfo;
import org.jetbrains.annotations.NotNull;
/**
@@ -25,13 +25,13 @@ public interface FilteringTaskCallback {
void started(int totalCount);
@NotNull
Action matched(@NotNull Value ref);
Action matched(@NotNull JavaReferenceInfo ref);
@NotNull
Action notMatched(@NotNull Value ref);
Action notMatched(@NotNull JavaReferenceInfo ref);
@NotNull
Action error(@NotNull Value ref, @NotNull String description);
Action error(@NotNull JavaReferenceInfo ref, @NotNull String description);
void completed(@NotNull FilteringResult reason);
@@ -9,13 +9,13 @@ import com.intellij.debugger.engine.SuspendContextImpl;
import com.intellij.debugger.engine.evaluation.EvaluationContext;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.engine.events.DebuggerContextCommandImpl;
import com.intellij.debugger.memory.agent.MemoryAgentUtil;
import com.intellij.debugger.memory.filtering.FilteringResult;
import com.intellij.debugger.memory.filtering.FilteringTask;
import com.intellij.debugger.memory.filtering.FilteringTaskCallback;
import com.intellij.debugger.memory.utils.AndroidUtil;
import com.intellij.debugger.memory.utils.ErrorsValueGroup;
import com.intellij.debugger.memory.utils.InstanceJavaValue;
import com.intellij.debugger.memory.utils.InstanceValueDescriptor;
import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl;
import com.intellij.debugger.ui.impl.watch.MessageDescriptor;
import com.intellij.debugger.ui.impl.watch.NodeManagerImpl;
@@ -41,8 +41,6 @@ import com.intellij.xdebugger.impl.ui.XDebuggerExpressionEditor;
import com.intellij.xdebugger.memory.ui.InstancesTree;
import com.intellij.xdebugger.memory.ui.InstancesViewBase;
import com.intellij.xdebugger.memory.utils.InstancesProvider;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.Value;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -184,8 +182,8 @@ class InstancesView extends InstancesViewBase {
final int limit = myIsAndroidVM
? AndroidUtil.ANDROID_INSTANCES_LIMIT
: DEFAULT_INSTANCES_LIMIT;
List<ObjectReference> instances = ContainerUtil
.map(getInstancesProvider().getInstances(limit + 1), referenceInfo -> ((JavaReferenceInfo)referenceInfo).getObjectReference());
List<JavaReferenceInfo> instances = ContainerUtil
.map(getInstancesProvider().getInstances(limit + 1), referenceInfo -> ((JavaReferenceInfo)referenceInfo));
final EvaluationContextImpl evaluationContext = myDebugProcess
.getDebuggerContext().createEvaluationContext();
@@ -195,9 +193,11 @@ class InstancesView extends InstancesViewBase {
instances = instances.subList(0, limit);
}
instances = MemoryAgentUtil.tryCalculateSizes(instances, myDebugProcess.getMemoryAgent());
if (evaluationContext != null) {
synchronized (myFilteringTaskLock) {
List<ObjectReference> finalInstances = instances;
List<JavaReferenceInfo> finalInstances = instances;
ApplicationManager.getApplication().runReadAction(() -> {
myFilteringTask = new MyFilteringWorker(finalInstances, myFilterConditionEditor.getExpression(), evaluationContext);
myFilteringTask.execute();
@@ -252,9 +252,6 @@ class InstancesView extends InstancesViewBase {
}
private class MyFilteringCallback implements FilteringTaskCallback {
private final ErrorsValueGroup myErrorsGroup = new ErrorsValueGroup();
private final EvaluationContextImpl myEvaluationContext;
@@ -284,8 +281,8 @@ class InstancesView extends InstancesViewBase {
@NotNull
@Override
public Action matched(@NotNull Value ref) {
final JavaValue val = new InstanceJavaValue(new InstanceValueDescriptor(myDebugProcess.getProject(), ref),
public Action matched(@NotNull JavaReferenceInfo ref) {
final JavaValue val = new InstanceJavaValue(ref.createDescriptor(myDebugProcess.getProject()),
myEvaluationContext, myNodeManager);
myMatchedCount++;
myProceedCount++;
@@ -298,7 +295,7 @@ class InstancesView extends InstancesViewBase {
@NotNull
@Override
public Action notMatched(@NotNull Value ref) {
public Action notMatched(@NotNull JavaReferenceInfo ref) {
myProceedCount++;
updateProgress();
@@ -307,8 +304,8 @@ class InstancesView extends InstancesViewBase {
@NotNull
@Override
public Action error(@NotNull Value ref, @NotNull String description) {
final JavaValue val = new InstanceJavaValue(new InstanceValueDescriptor(myDebugProcess.getProject(), ref),
public Action error(@NotNull JavaReferenceInfo ref, @NotNull String description) {
final JavaValue val = new InstanceJavaValue(ref.createDescriptor(myDebugProcess.getProject()),
myEvaluationContext, myNodeManager);
myErrorsGroup.addErrorValue(description, val);
myProceedCount++;
@@ -364,9 +361,9 @@ class InstancesView extends InstancesViewBase {
}
}
private static class MyValuesList implements FilteringTask.ValuesList {
private final List<? extends ObjectReference> myRefs;
private final List<? extends JavaReferenceInfo> myRefs;
MyValuesList(List<? extends ObjectReference> refs) {
MyValuesList(List<? extends JavaReferenceInfo> refs) {
myRefs = refs;
}
@@ -376,14 +373,14 @@ class InstancesView extends InstancesViewBase {
}
@Override
public ObjectReference get(int index) {
public JavaReferenceInfo get(int index) {
return myRefs.get(index);
}
}
private class MyFilteringWorker extends SwingWorker<Void, Void> {
private final FilteringTask myTask;
MyFilteringWorker(@NotNull List<ObjectReference> refs,
MyFilteringWorker(@NotNull List<JavaReferenceInfo> refs,
@NotNull XExpression expression,
@NotNull EvaluationContextImpl evaluationContext) {
myTask = new FilteringTask(myClassName, myDebugProcess, expression, new MyValuesList(refs),
@@ -1,6 +1,9 @@
// Copyright 2000-2018 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.ui;
import com.intellij.debugger.memory.utils.InstanceValueDescriptor;
import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl;
import com.intellij.openapi.project.Project;
import com.intellij.xdebugger.memory.ui.ReferenceInfo;
import com.sun.jdi.ObjectReference;
import org.jetbrains.annotations.NotNull;
@@ -12,6 +15,10 @@ public class JavaReferenceInfo implements ReferenceInfo {
this.objectReference = objectReference;
}
public ValueDescriptorImpl createDescriptor(@NotNull Project project) {
return new InstanceValueDescriptor(project, objectReference);
}
@NotNull
public ObjectReference getObjectReference() {
return objectReference;
@@ -0,0 +1,37 @@
// Copyright 2000-2019 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.ui;
import com.intellij.debugger.memory.utils.InstanceValueDescriptor;
import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl;
import com.intellij.openapi.project.Project;
import com.sun.jdi.ObjectReference;
import org.jetbrains.annotations.NotNull;
public class SizedReferenceInfo extends JavaReferenceInfo {
private final long mySize;
public SizedReferenceInfo(@NotNull ObjectReference objectReference, long size) {
super(objectReference);
mySize = size;
}
@Override
public ValueDescriptorImpl createDescriptor(@NotNull Project project) {
return new SizedValueDescriptor(project, getObjectReference());
}
public long size() {
return mySize;
}
private class SizedValueDescriptor extends InstanceValueDescriptor {
protected SizedValueDescriptor(@NotNull Project project, @NotNull ObjectReference value) {
super(project, value);
}
@Override
public String calcValueName() {
return " [" + mySize + "] " + super.calcValueName();
}
}
}