EA-254391 - T: AsyncStacksUtils.getProcessCapturedStack

GitOrigin-RevId: cfafd30740d8d683cf181ecb941440e3094cf000
This commit is contained in:
Egor Ushakov
2021-06-23 13:33:51 +00:00
committed by intellij-monorepo-bot
parent c2b779dd51
commit 9a70b43f71
7 changed files with 316 additions and 67 deletions
@@ -1,4 +1,4 @@
// 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.
// Copyright 2000-2021 JetBrains s.r.o. and contributors. 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.engine;
import com.intellij.debugger.engine.evaluation.EvaluateException;
@@ -6,10 +6,7 @@ import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.engine.requests.RequestManagerImpl;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.impl.DebuggerUtilsImpl;
import com.intellij.debugger.jdi.ClassesByNameProvider;
import com.intellij.debugger.jdi.GeneratedLocation;
import com.intellij.debugger.jdi.StackFrameProxyImpl;
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
import com.intellij.debugger.jdi.*;
import com.intellij.debugger.memory.utils.StackFrameItem;
import com.intellij.debugger.requests.ClassPrepareRequestor;
import com.intellij.debugger.settings.CaptureSettingsProvider;
@@ -111,18 +108,13 @@ public final class AsyncStacksUtils {
ClassesByNameProvider classesByName = ClassesByNameProvider.createCache(virtualMachineProxy.allClasses());
try (DataInputStream dis = new DataInputStream(new ByteArrayInputStream(value.getBytes(StandardCharsets.ISO_8859_1)))) {
while (dis.available() > 0) {
ProcessStackFrameItem item = null;
StackFrameItem item = null;
if (dis.readBoolean()) {
String className = dis.readUTF();
String methodName = dis.readUTF();
int line = dis.readInt();
ReferenceType classType = ContainerUtil.getFirstItem(classesByName.get(className));
if (classType == null) {
LOG.error("Unable to find loaded class " + className);
return null;
}
Location location = findLocation(process, classType, methodName, line);
item = new ProcessStackFrameItem(location, className, methodName);
Location location = findLocation(process, classesByName, className, methodName, line);
item = new StackFrameItem(location, null);
}
res.add(item);
}
@@ -201,44 +193,25 @@ public final class AsyncStacksUtils {
}
}
private static class ProcessStackFrameItem extends StackFrameItem {
final String myClass;
final String myMethod;
ProcessStackFrameItem(Location location, String aClass, String method) {
super(location, null);
myClass = aClass;
myMethod = method;
@NotNull
private static Location findLocation(DebugProcessImpl debugProcess,
@NotNull ClassesByNameProvider classesByName,
@NotNull String className,
@NotNull String methodName,
int line) {
ReferenceType classType = ContainerUtil.getFirstItem(classesByName.get(className));
if (classType == null) {
classType = new GeneratedReferenceType(debugProcess.getVirtualMachineProxy().getVirtualMachine(), className);
}
@NotNull
@Override
public String path() {
return myClass;
}
@NotNull
@Override
public String method() {
return myMethod;
}
@Override
public String toString() {
return myClass + "." + myMethod + ":" + line();
}
}
private static Location findLocation(DebugProcessImpl debugProcess, @NotNull ReferenceType type, String methodName, int line) {
if (line >= 0) {
for (Method method : DebuggerUtilsEx.declaredMethodsByName(type, methodName)) {
else if (line >= 0) {
for (Method method : DebuggerUtilsEx.declaredMethodsByName(classType, methodName)) {
List<Location> locations = DebuggerUtilsEx.locationsOfLine(method, line);
if (!locations.isEmpty()) {
return locations.get(0);
}
}
}
return new GeneratedLocation(debugProcess, type, methodName, line);
return new GeneratedLocation(classType, methodName, line);
}
public static void addAgentCapturePoints(EvaluationContextImpl evalContext, Properties properties) {
@@ -14,6 +14,7 @@ import com.intellij.debugger.engine.evaluation.*;
import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator;
import com.intellij.debugger.engine.evaluation.expression.UnBoxingEvaluator;
import com.intellij.debugger.engine.requests.RequestManagerImpl;
import com.intellij.debugger.jdi.GeneratedLocation;
import com.intellij.debugger.jdi.JvmtiError;
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
import com.intellij.debugger.requests.Requestor;
@@ -884,10 +885,14 @@ public abstract class DebuggerUtilsEx extends DebuggerUtils {
if (type != null) {
res.append(type.name()).append('.');
}
res.append(location.method().name());
res.append(getLocationMethodName(location));
return res.toString();
}
public static String getLocationMethodName(@NotNull Location location) {
return location instanceof GeneratedLocation ? ((GeneratedLocation)location).methodName() : location.method().name();
}
private static PsiElement getNextElement(PsiElement element) {
PsiElement sibling = element.getNextSibling();
if (sibling != null) return sibling;
@@ -1,23 +1,23 @@
// 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.
// Copyright 2000-2021 JetBrains s.r.o. and contributors. 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.jdi;
import com.intellij.debugger.engine.DebugProcessImpl;
import com.intellij.debugger.engine.DebuggerUtils;
import com.sun.jdi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
public class GeneratedLocation implements Location {
private final VirtualMachine myVirtualMachine;
private final int myLineNumber;
private final ReferenceType myReferenceType;
private final Method myMethod;
private final @NotNull ReferenceType myReferenceType;
private final @Nullable Method myMethod;
private final @NotNull String myMethodName;
public GeneratedLocation(DebugProcessImpl debugProcess, @NotNull ReferenceType type, String methodName, int lineNumber) {
myVirtualMachine = debugProcess.getVirtualMachineProxy().getVirtualMachine();
public GeneratedLocation(@NotNull ReferenceType type, @NotNull String methodName, int lineNumber) {
myLineNumber = lineNumber;
myReferenceType = type;
myMethodName = methodName;
myMethod = DebuggerUtils.findMethod(myReferenceType, methodName, null);
}
@@ -31,6 +31,11 @@ public class GeneratedLocation implements Location {
return myMethod;
}
@NotNull
public String methodName() {
return myMethodName;
}
@Override
public long codeIndex() {
return -2; // to be never equal to any LocationImpl
@@ -68,22 +73,23 @@ public class GeneratedLocation implements Location {
@Override
public VirtualMachine virtualMachine() {
return myVirtualMachine;
return myReferenceType.virtualMachine();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
GeneratedLocation location = (GeneratedLocation)o;
return Objects.equals(myMethod, location.myMethod) &&
myLineNumber == location.myLineNumber &&
Objects.equals(myVirtualMachine, location.myVirtualMachine);
public boolean equals(Object other) {
if (this == other) return true;
if (other == null || getClass() != other.getClass()) return false;
GeneratedLocation location = (GeneratedLocation)other;
return myLineNumber == location.myLineNumber &&
myReferenceType.equals(location.myReferenceType) &&
myMethodName.equals(location.myMethodName) &&
Objects.equals(virtualMachine(), location.virtualMachine());
}
@Override
public int hashCode() {
return Objects.hash(myMethod, myLineNumber);
return Objects.hash(myMethodName, myLineNumber);
}
// Same as in LocationImpl
@@ -97,6 +103,6 @@ public class GeneratedLocation implements Location {
}
public String toString() {
return myReferenceType.name() + ":" + myLineNumber;
return myReferenceType.name() + "." + myMethodName + ":" + myLineNumber;
}
}
@@ -0,0 +1,264 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. 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.jdi;
import com.jetbrains.jdi.JNITypeParser;
import com.sun.jdi.*;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class GeneratedReferenceType implements ReferenceType {
private final @NotNull VirtualMachine myVm;
private final @NotNull String myName;
public GeneratedReferenceType(@NotNull VirtualMachine vm, @NotNull String name) {
myVm = vm;
myName = name;
}
@Override
public String name() {
return myName;
}
@Override
public String genericSignature() {
return null;
}
@Override
public ClassLoaderReference classLoader() {
return null;
}
@Override
public String sourceName() throws AbsentInformationException {
throw new AbsentInformationException();
}
@Override
public List<String> sourceNames(String stratum) throws AbsentInformationException {
throw new AbsentInformationException();
}
@Override
public List<String> sourcePaths(String stratum) throws AbsentInformationException {
throw new AbsentInformationException();
}
@Override
public String sourceDebugExtension() throws AbsentInformationException {
throw new AbsentInformationException();
}
@Override
public boolean isStatic() {
return false;
}
@Override
public boolean isAbstract() {
return false;
}
@Override
public boolean isFinal() {
return false;
}
@Override
public boolean isPrepared() {
return false;
}
@Override
public boolean isVerified() {
return false;
}
@Override
public boolean isInitialized() {
return false;
}
@Override
public boolean failedToInitialize() {
return false;
}
@Override
public List<Field> fields() {
return Collections.emptyList();
}
@Override
public List<Field> visibleFields() {
return Collections.emptyList();
}
@Override
public List<Field> allFields() {
return Collections.emptyList();
}
@Override
public Field fieldByName(String fieldName) {
return null;
}
@Override
public List<Method> methods() {
return Collections.emptyList();
}
@Override
public List<Method> visibleMethods() {
return Collections.emptyList();
}
@Override
public List<Method> allMethods() {
return Collections.emptyList();
}
@Override
public List<Method> methodsByName(String name) {
return Collections.emptyList();
}
@Override
public List<Method> methodsByName(String name, String signature) {
return Collections.emptyList();
}
@Override
public List<ReferenceType> nestedTypes() {
return Collections.emptyList();
}
@Override
public Value getValue(Field field) {
return null;
}
@Override
public Map<Field, Value> getValues(List<? extends Field> fields) {
return Collections.emptyMap();
}
@Override
public ClassObjectReference classObject() {
return null;
}
@Override
public List<Location> allLineLocations() throws AbsentInformationException {
return Collections.emptyList();
}
@Override
public List<Location> allLineLocations(String stratum, String sourceName) throws AbsentInformationException {
return Collections.emptyList();
}
@Override
public List<Location> locationsOfLine(int lineNumber) throws AbsentInformationException {
return Collections.emptyList();
}
@Override
public List<Location> locationsOfLine(String stratum, String sourceName, int lineNumber) throws AbsentInformationException {
return Collections.emptyList();
}
@Override
public List<String> availableStrata() {
return List.of(myVm.getDefaultStratum());
}
@Override
public String defaultStratum() {
return myVm.getDefaultStratum();
}
@Override
public List<ObjectReference> instances(long maxInstances) {
return Collections.emptyList();
}
@Override
public int majorVersion() {
return 0;
}
@Override
public int minorVersion() {
return 0;
}
@Override
public int constantPoolCount() {
return 0;
}
@Override
public byte[] constantPool() {
return new byte[0];
}
@Override
public int modifiers() {
return 0;
}
@Override
public boolean isPrivate() {
return false;
}
@Override
public boolean isPackagePrivate() {
return false;
}
@Override
public boolean isProtected() {
return false;
}
@Override
public boolean isPublic() {
return false;
}
@Override
public String signature() {
return JNITypeParser.typeNameToSignature(myName);
}
@Override
public VirtualMachine virtualMachine() {
return myVm;
}
@Override
public int compareTo(@NotNull ReferenceType o) {
return 0;
}
@Override
public boolean equals(Object other) {
if (this == other) return true;
if (other == null || getClass() != other.getClass()) return false;
GeneratedReferenceType type = (GeneratedReferenceType)other;
return myName.equals(type.myName) && myVm.equals(type.myVm);
}
@Override
public int hashCode() {
return Objects.hash(myName);
}
}
@@ -1,4 +1,4 @@
// 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.
// Copyright 2000-2021 JetBrains s.r.o. and contributors. 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.utils;
import com.intellij.debugger.JavaDebuggerBundle;
@@ -82,7 +82,7 @@ public class StackFrameItem {
@NotNull
public String method() {
return myLocation.method().name();
return DebuggerUtilsEx.getLocationMethodName(myLocation);
}
public int line() {
@@ -1,4 +1,4 @@
// 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.
// Copyright 2000-2021 JetBrains s.r.o. and contributors. 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.ui.breakpoints;
import com.intellij.debugger.JavaDebuggerBundle;
@@ -10,6 +10,7 @@ import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilderImpl;
import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator;
import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluatorImpl;
import com.intellij.debugger.engine.events.SuspendContextCommandImpl;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.jdi.DecompiledLocalVariable;
import com.intellij.debugger.jdi.StackFrameProxyImpl;
import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
@@ -163,7 +164,7 @@ public class StackCapturingLineBreakpoint extends SyntheticMethodBreakpoint {
try {
Location location = frame.location();
String className = location.declaringType().name();
String methodName = location.method().name();
String methodName = DebuggerUtilsEx.getLocationMethodName(location);
for (StackCapturingLineBreakpoint b : captureBreakpoints) {
String insertClassName = b.myCapturePoint.myInsertClassName;
@@ -32,6 +32,6 @@ class LocationCache(val context: DefaultExecutionContext) {
} catch (ignored: AbsentInformationException) {
}
}
return GeneratedLocation(context.debugProcess, type, methodName, line)
return GeneratedLocation(type, methodName, line)
}
}