[memory-agent] Update version: 0.0.7 and integrate new data format

This commit is contained in:
Vitaliy.Bibaev
2019-01-31 18:33:08 +03:00
parent 42f80e2e10
commit 4d7cacbf01
10 changed files with 102 additions and 89 deletions
+3 -3
View File
@@ -1,12 +1,12 @@
<component name="libraryTable">
<library name="debugger-memory-agent" type="repository">
<properties maven-id="org.jetbrains.intellij.deps:debugger-memory-agent:0.0.5" />
<properties maven-id="org.jetbrains.intellij.deps:debugger-memory-agent:0.0.7" />
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/intellij/deps/debugger-memory-agent/0.0.5/debugger-memory-agent-0.0.5.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/intellij/deps/debugger-memory-agent/0.0.7/debugger-memory-agent-0.0.7.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/intellij/deps/debugger-memory-agent/0.0.5/debugger-memory-agent-0.0.5-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/intellij/deps/debugger-memory-agent/0.0.7/debugger-memory-agent-0.0.7-sources.jar!/" />
</SOURCES>
</library>
</component>
@@ -18,11 +18,12 @@ import com.sun.jdi.ObjectReference;
import org.jetbrains.annotations.NotNull;
public class ShowGarbageCollectorRootsAction extends NativeAgentActionBase {
private static final int DEFAULT_OBJECTS_LIMIT = 1000;
@Override
protected void perform(@NotNull MemoryAgent memoryAgent,
@NotNull ObjectReference reference,
@NotNull XValueNodeImpl node) throws EvaluateException {
ReferringObjectsProvider roots = memoryAgent.canFindGcRoots() ? memoryAgent.findGcRoots(reference) : null;
ReferringObjectsProvider roots = memoryAgent.canFindGcRoots() ? memoryAgent.findGcRoots(reference, DEFAULT_OBJECTS_LIMIT) : null;
if (roots == null) {
XDebuggerManagerImpl.NOTIFICATION_GROUP.createNotification("This feature is unavailable", NotificationType.INFORMATION);
return;
@@ -106,7 +106,7 @@ public class AgentLoader {
}
@Override
public ReferringObjectsProvider findGcRoots(@NotNull ObjectReference reference) {
public ReferringObjectsProvider findGcRoots(@NotNull ObjectReference reference, int limit) {
throw new UnsupportedOperationException();
}
}
@@ -23,5 +23,5 @@ public interface MemoryAgent {
boolean canFindGcRoots();
@Nullable
ReferringObjectsProvider findGcRoots(@NotNull ObjectReference reference) throws EvaluateException;
ReferringObjectsProvider findGcRoots(@NotNull ObjectReference reference, int limit) throws EvaluateException;
}
@@ -11,13 +11,11 @@ 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.ClassType;
import com.sun.jdi.Method;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.Value;
import com.sun.jdi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -60,7 +58,7 @@ public class MemoryAgentImpl implements MemoryAgent {
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;
return result != null ? LongValueParser.INSTANCE.parse(result) : -1;
}
@Override
@@ -83,11 +81,12 @@ public class MemoryAgentImpl implements MemoryAgent {
@Nullable
@Override
public ReferringObjectsProvider findGcRoots(@NotNull ObjectReference reference) throws EvaluateException {
public ReferringObjectsProvider findGcRoots(@NotNull ObjectReference reference, int limit) 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);
IntegerValue limitValue = myDebugProcess.getVirtualMachineProxy().mirrorOf(limit);
Value value = callMethod(GARBAGE_COLLECTOR_ROOTS_METHOD_NAME, Arrays.asList(reference, limitValue));
return value == null ? null : GcRootsPathsParser.INSTANCE.parse(value);
}
@Override
@@ -0,0 +1,8 @@
// 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;
public class UnexpectedValueFormatException extends RuntimeException {
public UnexpectedValueFormatException(String message) {
super(message);
}
}
@@ -1,11 +0,0 @@
// 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
}
}
@@ -1,62 +1,20 @@
// 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.intellij.debugger.memory.agent.MemoryAgentReferringObjectProvider
import com.intellij.debugger.engine.ReferringObjectsProvider
import com.intellij.openapi.diagnostic.Logger
import com.intellij.debugger.memory.agent.MemoryAgentReferringObjectProvider
import com.intellij.debugger.memory.agent.UnexpectedValueFormatException
import com.sun.jdi.ArrayReference
import com.sun.jdi.IntegerValue
import com.sun.jdi.ObjectReference
import com.sun.jdi.Value
import java.util.ArrayList
class GcRootsPathsParser : ResultParser<ReferringObjectsProvider> {
private companion object {
val LOG = Logger.getInstance(GcRootsPathsParser::class.java)
}
object GcRootsPathsParser : ResultParser<ReferringObjectsProvider> {
override fun parse(value: Value): ReferringObjectsProvider {
if (value is ArrayReference) {
LOG.assertTrue(value.length() == 2, "Array must represent 2 values: objects and backward references")
val values = parseValues(value.getValue(0))
val backwardReferences = parseBackwardReferences(value.getValue(1))
if (value.length() != 2) throw UnexpectedValueFormatException("Array must represent 2 values: objects and backward references")
val values = ObjectReferencesParser.parse(value.getValue(0))
val backwardReferences = BackwardReferencesParser.parse(value.getValue(1))
return MemoryAgentReferringObjectProvider(values, backwardReferences)
}
throw AssertionError("Incorrect result format: array of arrays is expected")
}
private fun parseBackwardReferences(value: Value): List<List<Int>> {
if (value is ArrayReference) {
val result = ArrayList<List<Int>>()
for (item in value.values) {
if (item !is ArrayReference || "int" == item.type().name()) {
throw AssertionError("Incorrect result format: int array expected")
}
val ints = item.values.map { x -> (x as IntegerValue).value() }
result.add(ints)
}
return result
}
throw AssertionError("Incorrect result format: array with nested int arrays expected")
}
private fun parseValues(value: Value): List<ObjectReference> {
if (value is ArrayReference) {
val result = ArrayList<ObjectReference>()
for (item in value.values) {
if (item !is ObjectReference) break
result.add(item)
}
if (result.size != value.length()) {
throw AssertionError("All values should be object references but some of them are not")
}
return result
}
throw AssertionError("Incorrect result format: array with object references expected")
throw UnexpectedValueFormatException("Array of arrays is expected")
}
}
@@ -1,15 +0,0 @@
// 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.PrimitiveValue
import com.sun.jdi.Value
class LongValueParser : ResultParser<Long> {
override fun parse(value: Value): Long {
if (value is PrimitiveValue) {
return value.longValue()
}
throw IllegalArgumentException("Unexpected argument. Primitive value is expected")
}
}
@@ -0,0 +1,73 @@
// 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.intellij.debugger.memory.agent.UnexpectedValueFormatException
import com.sun.jdi.*
import java.util.ArrayList
object BooleanParser : ResultParser<Boolean> {
override fun parse(value: Value): Boolean {
return (value as? BooleanValue)?.value() ?: false
}
}
object LongValueParser : ResultParser<Long> {
override fun parse(value: Value): Long {
if (value is PrimitiveValue) {
return value.longValue()
}
throw UnexpectedValueFormatException("Primitive value is expected")
}
}
object ObjectReferencesParser : ResultParser<List<ObjectReference>> {
override fun parse(value: Value): List<ObjectReference> {
if (value is ArrayReference) {
val result = ArrayList<ObjectReference>()
for (item in value.values) {
if (item !is ObjectReference) break
result.add(item)
}
if (result.size != value.length()) {
throw UnexpectedValueFormatException(
"All values should be object references but some of them are not")
}
return result
}
throw UnexpectedValueFormatException("Array with object references expected")
}
}
object BackwardReferencesParser : ResultParser<List<List<Int>>> {
override fun parse(value: Value): List<List<Int>> {
if (value !is ArrayReference) throw UnexpectedValueFormatException("Array with nested arrays expected")
val result = ArrayList<List<Int>>()
for (linksInfo in value.values) {
if (linksInfo !is ArrayReference) throw UnexpectedValueFormatException("Object references information should be represented by array")
val indices = IntArrayParser.parse(linksInfo.getValue(0))
.distinct() // drop duplicates
.filter { it != -1 } // drop gc roots
// TODO: parse kinds and infos as well
result.add(indices)
}
return result
}
}
object IntArrayParser : ResultParser<List<Int>> {
override fun parse(value: Value): List<Int> {
if (value !is ArrayReference) throw UnexpectedValueFormatException("Array expected")
val items = value.values
if (items.isEmpty()) return emptyList()
if (items[0] !is IntegerValue) throw UnexpectedValueFormatException("array elements should be integers")
return items.map { it as IntegerValue }.map(IntegerValue::value)
}
}