Integrate memory agent into DebugProcessImpl

This commit is contained in:
Vitaliy.Bibaev
2019-01-19 18:22:31 +03:00
parent 4588e35952
commit 33e77658d1
11 changed files with 219 additions and 79 deletions
@@ -13,6 +13,7 @@ import com.intellij.debugger.impl.DebuggerUtilsImpl;
import com.intellij.debugger.impl.PrioritizedTask;
import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
import com.intellij.debugger.memory.agent.MemoryAgentManager;
import com.intellij.debugger.requests.Requestor;
import com.intellij.debugger.settings.DebuggerSettings;
import com.intellij.debugger.ui.breakpoints.Breakpoint;
@@ -364,6 +365,10 @@ public class DebugProcessEvents extends DebugProcessImpl {
AsyncStacksUtils.setupAgent(this);
}
if (canBeModified) {
MemoryAgentManager.loadAgentProxy(this, agent -> myMemoryAgent = agent);
}
// breakpoints should be initialized after all processAttached listeners work
ApplicationManager.getApplication().runReadAction(() -> {
XDebugSession session = getSession().getXDebugSession();
@@ -19,6 +19,7 @@ import com.intellij.debugger.jdi.EmptyConnectorArgument;
import com.intellij.debugger.jdi.StackFrameProxyImpl;
import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
import com.intellij.debugger.memory.agent.MemoryAgent;
import com.intellij.debugger.settings.DebuggerSettings;
import com.intellij.debugger.settings.NodeRendererSettings;
import com.intellij.debugger.ui.breakpoints.BreakpointManager;
@@ -103,6 +104,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
private final RequestManagerImpl myRequestManager;
private volatile VirtualMachineProxyImpl myVirtualMachineProxy = null;
@Nullable protected volatile MemoryAgent myMemoryAgent;
protected final EventDispatcher<DebugProcessListener> myDebugProcessDispatcher = EventDispatcher.create(DebugProcessListener.class);
protected final EventDispatcher<EvaluationListener> myEvaluationDispatcher = EventDispatcher.create(EvaluationListener.class);
@@ -913,6 +915,11 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
return myDebuggerManagerThread;
}
@Nullable
public MemoryAgent getMemoryAgent() {
return myMemoryAgent;
}
private static int getInvokePolicy(SuspendContext suspendContext) {
if (suspendContext.getSuspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD ||
isResumeOnlyCurrentThread() ||
@@ -1,8 +1,7 @@
// 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.action;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.memory.agent.AgentLoader;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.memory.agent.MemoryAgent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.messages.MessageDialog;
@@ -11,19 +10,20 @@ import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
import com.sun.jdi.ObjectReference;
import org.jetbrains.annotations.NotNull;
/**
* @author Vitaliy.Bibaev
*/
public class CalculateRetainedSizeAction extends NativeAgentActionBase {
@Override
protected void perform(@NotNull EvaluationContextImpl evaluationContext,
protected void perform(@NotNull MemoryAgent memoryAgent,
@NotNull ObjectReference reference,
@NotNull XValueNodeImpl node) {
MemoryAgent memoryAgent = new AgentLoader().load(evaluationContext, evaluationContext.getDebugProcess().getVirtualMachineProxy());
@NotNull XValueNodeImpl node) throws EvaluateException {
long size = memoryAgent.evaluateObjectSize(reference);
ApplicationManager.getApplication().invokeLater(
() -> new MessageDialog(node.getTree().getProject(), String.valueOf(size), "Size of the Object",
ArrayUtil.EMPTY_STRING_ARRAY, 0, null, false)
.show());
}
@Override
protected boolean isEnabled(@NotNull MemoryAgent agent) {
return agent.canEvaluateObjectSize();
}
}
@@ -2,20 +2,17 @@
package com.intellij.debugger.memory.action;
import com.intellij.debugger.engine.DebugProcessImpl;
import com.intellij.debugger.engine.JavaValue;
import com.intellij.debugger.engine.SuspendContextImpl;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.engine.JavaDebugProcess;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.managerThread.DebuggerCommand;
import com.intellij.debugger.memory.agent.MemoryAgent;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebuggerManager;
import com.intellij.xdebugger.frame.XSuspendContext;
import com.intellij.xdebugger.frame.XValue;
import com.intellij.xdebugger.impl.XDebuggerManagerImpl;
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.Value;
import org.jetbrains.annotations.NotNull;
public abstract class NativeAgentActionBase extends DebuggerTreeAction {
@@ -24,20 +21,19 @@ public abstract class NativeAgentActionBase extends DebuggerTreeAction {
@Override
protected void perform(XValueNodeImpl node, @NotNull String nodeName, AnActionEvent e) {
Project project = node.getTree().getProject();
XValue container = node.getValueContainer();
XDebugSession currentSession = XDebuggerManager.getInstance(project).getCurrentSession();
XSuspendContext suspendContext = currentSession != null ? currentSession.getSuspendContext() : null;
DebugProcessImpl debugProcess =
suspendContext instanceof SuspendContextImpl ? ((SuspendContextImpl)suspendContext).getDebugProcess() : null;
if (debugProcess == null) return;
DebugProcessImpl debugProcess = JavaDebugProcess.getCurrentDebugProcess(project);
ObjectReference reference = getObjectReference(node);
if (debugProcess == null || reference == null) return;
debugProcess.getManagerThread().invokeCommand(new DebuggerCommand() {
@Override
public void action() {
if (container instanceof JavaValue) {
EvaluationContextImpl evaluationContext = debugProcess.getDebuggerContext().createEvaluationContext();
if (evaluationContext == null) return;
Value value = ((JavaValue)container).getDescriptor().getValue();
perform(evaluationContext, (ObjectReference)value, node);
MemoryAgent memoryAgent = debugProcess.getMemoryAgent();
LOG.assertTrue(memoryAgent != null);
try {
perform(memoryAgent, reference, node);
}
catch (EvaluateException ex) {
XDebuggerManagerImpl.NOTIFICATION_GROUP.createNotification("Action failed", NotificationType.ERROR);
}
}
@@ -51,15 +47,20 @@ public abstract class NativeAgentActionBase extends DebuggerTreeAction {
@Override
protected boolean isEnabled(@NotNull XValueNodeImpl node, @NotNull AnActionEvent e) {
if (!super.isEnabled(node, e)) return false;
XValue container = node.getValueContainer();
if (container instanceof JavaValue) {
if (((JavaValue)container).getDescriptor().getValue() instanceof ObjectReference) return true;
DebugProcessImpl debugProcess = JavaDebugProcess.getCurrentDebugProcess(node.getTree().getProject());
MemoryAgent memoryAgent = debugProcess == null ? null : debugProcess.getMemoryAgent();
if (memoryAgent == null || !memoryAgent.isLoaded()) {
e.getPresentation().setVisible(false);
return false;
}
ObjectReference reference = getObjectReference(node);
return false;
return reference != null && isEnabled(memoryAgent);
}
protected abstract void perform(@NotNull EvaluationContextImpl evaluationContext,
protected abstract boolean isEnabled(@NotNull MemoryAgent agent);
protected abstract void perform(@NotNull MemoryAgent agent,
@NotNull ObjectReference reference,
@NotNull XValueNodeImpl node);
@NotNull XValueNodeImpl node) throws EvaluateException;
}
@@ -3,14 +3,13 @@ package com.intellij.debugger.memory.action;
import com.intellij.debugger.actions.JavaReferringObjectsValue;
import com.intellij.debugger.engine.JavaValue;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
import com.intellij.debugger.memory.agent.AgentLoader;
import com.intellij.debugger.memory.agent.MemoryAgent;
import com.intellij.debugger.engine.ReferringObjectsProvider;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.memory.agent.MemoryAgent;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.impl.XDebuggerManagerImpl;
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
import com.intellij.xdebugger.impl.ui.tree.XInspectDialog;
@@ -20,11 +19,9 @@ import org.jetbrains.annotations.NotNull;
public class ShowGarbageCollectorRootsAction extends NativeAgentActionBase {
@Override
protected void perform(@NotNull EvaluationContextImpl evaluationContext,
protected void perform(@NotNull MemoryAgent memoryAgent,
@NotNull ObjectReference reference,
@NotNull XValueNodeImpl node) {
VirtualMachineProxyImpl virtualMachineProxy = evaluationContext.getDebugProcess().getVirtualMachineProxy();
MemoryAgent memoryAgent = new AgentLoader().load(evaluationContext, virtualMachineProxy);
@NotNull XValueNodeImpl node) throws EvaluateException {
ReferringObjectsProvider roots = memoryAgent.canFindGcRoots() ? memoryAgent.findGcRoots(reference) : null;
if (roots == null) {
XDebuggerManagerImpl.NOTIFICATION_GROUP.createNotification("This feature is unavailable", NotificationType.INFORMATION);
@@ -34,14 +31,20 @@ public class ShowGarbageCollectorRootsAction extends NativeAgentActionBase {
() -> {
XDebuggerTree tree = node.getTree();
JavaValue javaValue = (JavaValue)node.getValueContainer();
XDebugSession session = javaValue.getEvaluationContext().getDebugProcess().getSession().getXDebugSession();
JavaReferringObjectsValue value = new JavaReferringObjectsValue(javaValue, roots, false);
XInspectDialog dialog =
new XInspectDialog(tree.getProject(), tree.getEditorsProvider(), tree.getSourcePosition(), StringUtil.notNullize(node.getName()),
value, tree.getValueMarkers(),
evaluationContext.getDebugProcess().getSession().getXDebugSession(), false);
session, false);
dialog.setTitle("Paths to GC Roots");
dialog.show();
}
);
}
@Override
protected boolean isEnabled(@NotNull MemoryAgent agent) {
return agent.canFindGcRoots();
}
}
@@ -22,20 +22,25 @@ import java.util.List;
* @author Vitaliy.Bibaev
*/
public class AgentLoader {
public static final MemoryAgent DEFAULT_PROXY = new MyDisabledMemoryAgent();
private static final Logger LOG = Logger.getInstance(AgentLoader.class);
private static final MemoryAgent DEFAULT_PROXY = new MyDisabledMemoryAgent();
@NotNull
public MemoryAgent load(@NotNull EvaluationContextImpl evaluationContext, @NotNull VirtualMachineProxy virtualMachine) {
DebuggerManagerThreadImpl.assertIsManagerThread();
try {
ClassType classType = ensureClassLoaded(evaluationContext, virtualMachine);
return classType == null ? DEFAULT_PROXY : new MemoryAgentImpl(evaluationContext, classType);
if (classType != null) {
MemoryAgentImpl agent = new MemoryAgentImpl(evaluationContext.getDebugProcess(), classType);
agent.initializeCapabilities();
return agent.isLoaded() ? agent : DEFAULT_PROXY;
}
}
catch (EvaluateException e) {
LOG.error("Could not load proxy class", e);
return DEFAULT_PROXY;
LOG.info("Could not load proxy class", e);
}
return DEFAULT_PROXY;
}
@Nullable
@@ -69,6 +74,11 @@ public class AgentLoader {
}
private static class MyDisabledMemoryAgent implements MemoryAgent {
@Override
public boolean isLoaded() {
return false;
}
@Override
public boolean canEvaluateObjectSize() {
return false;
@@ -2,6 +2,7 @@
package com.intellij.debugger.memory.agent;
import com.intellij.debugger.engine.ReferringObjectsProvider;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.sun.jdi.ObjectReference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -9,16 +10,18 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
public interface MemoryAgent {
boolean isLoaded();
boolean canEvaluateObjectSize();
long evaluateObjectSize(@NotNull ObjectReference reference);
long evaluateObjectSize(@NotNull ObjectReference reference) throws EvaluateException;
boolean canEvaluateObjectsSizes();
List<Long> evaluateObjectsSizes(@NotNull List<ObjectReference> references);
List<Long> evaluateObjectsSizes(@NotNull List<ObjectReference> references) throws EvaluateException;
boolean canFindGcRoots();
@Nullable
ReferringObjectsProvider findGcRoots(@NotNull ObjectReference reference);
ReferringObjectsProvider findGcRoots(@NotNull ObjectReference reference) throws EvaluateException;
}
@@ -1,13 +1,20 @@
// 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.agent;
import com.intellij.debugger.engine.DebugProcessImpl;
import com.intellij.debugger.engine.DebuggerManagerThreadImpl;
import com.intellij.debugger.engine.ReferringObjectsProvider;
import com.intellij.debugger.engine.SuspendContextImpl;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.memory.agent.parsers.BooleanParser;
import com.intellij.debugger.memory.agent.parsers.GcRootsPathsParser;
import com.intellij.debugger.memory.agent.parsers.LongValueParser;
import com.intellij.openapi.diagnostic.Logger;
import com.sun.jdi.*;
import com.sun.jdi.ClassType;
import com.sun.jdi.Method;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.Value;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -20,24 +27,37 @@ public class MemoryAgentImpl implements MemoryAgent {
private static final Logger LOG = Logger.getInstance(MemoryAgentImpl.class);
private static final String SIZE_OF_SINGLE_OBJECT_METHOD_NAME = "size";
private static final String SIZE_OF_OBJECTS_METHOD_NAME = "size";
private static final String SIZE_OF_OBJECTS_METHOD_NAME = "sizes";
private static final String GARBAGE_COLLECTOR_ROOTS_METHOD_NAME = "gcRoots";
private final EvaluationContextImpl myEvaluationContext;
private final DebugProcessImpl myDebugProcess;
private final ClassType myProxyClassType;
public MemoryAgentImpl(@NotNull EvaluationContextImpl context, @NotNull ClassType reference) {
myEvaluationContext = context;
private volatile boolean myIsLoaded;
private volatile boolean myCanFindGcRoots;
private volatile boolean myCanEstimateObjectSize;
private volatile boolean myCanEstimateObjectsSizes;
public MemoryAgentImpl(@NotNull DebugProcessImpl debugProcess, @NotNull ClassType reference) {
myDebugProcess = debugProcess;
myProxyClassType = reference;
}
public void initializeCapabilities() {
DebuggerManagerThreadImpl.assertIsManagerThread();
myIsLoaded = checkCapability("isLoaded");
myCanFindGcRoots = checkCapability("canFindGcRoots");
myCanEstimateObjectSize = checkCapability("canEstimateObjectSize");
myCanEstimateObjectsSizes = checkCapability("canEstimateObjectsSizes");
}
@Override
public boolean canEvaluateObjectSize() {
return !myProxyClassType.methodsByName(SIZE_OF_SINGLE_OBJECT_METHOD_NAME).isEmpty();
return myCanEstimateObjectSize;
}
@Override
public long evaluateObjectSize(@NotNull ObjectReference reference) {
public long evaluateObjectSize(@NotNull ObjectReference reference) throws EvaluateException {
if (!canEvaluateObjectSize()) throw new UnsupportedOperationException();
Value result = callMethod(SIZE_OF_SINGLE_OBJECT_METHOD_NAME, Collections.singletonList(reference));
return result != null ? new LongValueParser().parse(result) : -1;
@@ -45,11 +65,11 @@ public class MemoryAgentImpl implements MemoryAgent {
@Override
public boolean canEvaluateObjectsSizes() {
return !myProxyClassType.methodsByName(SIZE_OF_OBJECTS_METHOD_NAME).isEmpty();
return myCanEstimateObjectsSizes;
}
@Override
public List<Long> evaluateObjectsSizes(@NotNull List<ObjectReference> references) {
public List<Long> evaluateObjectsSizes(@NotNull List<ObjectReference> references) throws EvaluateException {
if (!canEvaluateObjectsSizes()) throw new UnsupportedOperationException();
Value result = callMethod(SIZE_OF_OBJECTS_METHOD_NAME, references);
// TODO: Implement method and conversion
@@ -58,41 +78,52 @@ public class MemoryAgentImpl implements MemoryAgent {
@Override
public boolean canFindGcRoots() {
return !myProxyClassType.methodsByName(GARBAGE_COLLECTOR_ROOTS_METHOD_NAME).isEmpty();
return myCanFindGcRoots;
}
@Nullable
@Override
public ReferringObjectsProvider findGcRoots(@NotNull ObjectReference reference) {
public ReferringObjectsProvider findGcRoots(@NotNull ObjectReference reference) throws EvaluateException {
if (!canFindGcRoots()) throw new UnsupportedOperationException();
Value value = callMethod(GARBAGE_COLLECTOR_ROOTS_METHOD_NAME, Collections.singletonList(reference));
return value == null ? null : new GcRootsPathsParser().parse(value);
}
@Override
public boolean isLoaded() {
return myIsLoaded;
}
private boolean checkCapability(String methodName) {
try {
Value value = callMethod(methodName, Collections.emptyList());
return value != null && BooleanParser.INSTANCE.parse(value);
}
catch (EvaluateException e) {
return false;
}
}
@Nullable
private Value callMethod(@NotNull String methodName,
@NotNull List<? extends Value> args) {
@NotNull List<? extends Value> args) throws EvaluateException {
DebuggerManagerThreadImpl.assertIsManagerThread();
List<Method> methods = myProxyClassType.methodsByName(methodName);
if (methods.isEmpty()) {
LOG.error("Method \"" + methodName + "\" not found");
LOG.warn("Method \"" + methodName + "\" not found");
return null;
}
if (methods.size() > 1) {
LOG.warn("Too many methods \"" + methodName + "\" found. Count: " + methods.size());
LOG.warn("Too many methods \"" + methodName + "\" found. Count: " + methods);
}
Method method = methods.get(0);
if (!method.isStatic()) {
LOG.error("Utility method should be static");
}
try {
return myEvaluationContext.getDebugProcess().invokeMethod(myEvaluationContext, myProxyClassType, method, args);
}
catch (EvaluateException e) {
LOG.error("Something went wrong", e);
}
return null;
SuspendContextImpl suspendContext = myDebugProcess.getSuspendManager().getPausedContext();
EvaluationContextImpl evaluationContext = new EvaluationContextImpl(suspendContext, suspendContext.getFrameProxy());
return myDebugProcess.invokeMethod(evaluationContext, myProxyClassType, method, args);
}
}
@@ -1,25 +1,95 @@
// 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.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.EvaluationContextImpl;
import com.intellij.debugger.jdi.StackFrameProxyImpl;
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 org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
public class MemoryAgentManager {
private static final Logger LOG = Logger.getInstance(MemoryAgentManager.class);
public static void addMemoryAgent(JavaParameters parameters) {
if (!Registry.is("debugger.enable.memory.agent")) return;
ParametersList parametersList = parameters.getVMParametersList();
if (parametersList.getParameters().stream().anyMatch(x -> x.contains("memory_agent"))) return;
File extractedAgent = new AgentExtractor().extract();
if (extractedAgent == null) {
LOG.warn("Could not extract agent");
if (!Registry.is("debugger.enable.memory.agent")) {
return;
}
ParametersList parametersList = parameters.getVMParametersList();
if (parametersList.getParameters().stream().anyMatch(x -> x.contains("memory_agent"))) return;
File extractedAgent = null;
String errorMessage = null;
long start = System.currentTimeMillis();
try {
extractedAgent = ApplicationManager.getApplication()
.executeOnPooledThread(() -> new AgentExtractor().extract()).get(1, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
errorMessage = "Interrupted";
}
catch (ExecutionException e) {
LOG.warn(e.getCause());
errorMessage = "Exception thrown (see logs for details)";
}
catch (TimeoutException e) {
errorMessage = "Timeout";
}
if (errorMessage != null || extractedAgent == null) {
LOG.warn("Could not extract agent: " + errorMessage);
return;
}
LOG.info("Memory agent extracting took " + (System.currentTimeMillis() - start) + " ms");
parametersList.add("-agentpath:" + extractedAgent.getAbsolutePath());
}
public static void loadAgentProxy(@NotNull DebugProcessImpl debugProcess, @NotNull Consumer<MemoryAgent> agentLoaded) {
debugProcess.addDebugProcessListener(new DebugProcessAdapterImpl() {
@Override
public void paused(SuspendContextImpl suspendContext) {
MemoryAgent memoryAgent = initMemoryAgent(suspendContext);
if (memoryAgent == null) {
LOG.warn("Could not initialize memory agent.");
return;
}
agentLoaded.accept(memoryAgent);
debugProcess.removeDebugProcessListener(this);
}
@Nullable
private MemoryAgent initMemoryAgent(@NotNull SuspendContextImpl suspendContext) {
if (!Registry.is("debugger.enable.memory.agent")) {
LOG.info("Memory agent disabled by registry key");
return AgentLoader.DEFAULT_PROXY;
}
StackFrameProxyImpl frameProxy = suspendContext.getFrameProxy();
if (frameProxy == null) {
LOG.warn("frame proxy is not available");
return null;
}
long start = System.currentTimeMillis();
EvaluationContextImpl evaluationContext = new EvaluationContextImpl(suspendContext, frameProxy);
MemoryAgent agent = new AgentLoader().load(evaluationContext, debugProcess.getVirtualMachineProxy());
LOG.info("Memory agent loading took " + (System.currentTimeMillis() - start) + " ms");
return agent;
}
});
}
}
@@ -0,0 +1,11 @@
// 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.agent.parsers
import com.sun.jdi.BooleanValue
import com.sun.jdi.Value
object BooleanParser : ResultParser<Boolean> {
override fun parse(value: Value): Boolean {
return (value as? BooleanValue)?.value() ?: false
}
}
@@ -14,8 +14,7 @@ class AgentExtractor {
return@let if (SystemInfo.is32Bit) PlatformType.WINDOWS32 else PlatformType.WINDOWS64
}
fun extract(): File? {
// TODO: assert not EDT
fun extract(): File {
val file = FileUtil.createTempFile("${platform.prefix}memory_agent", platform.suffix, true)
val agentFileName = "${platform.prefix}memory_agent${platform.suffix}"
val inputStream = AgentExtractor::class.java.classLoader.getResourceAsStream("bin/$agentFileName")