From 4c4ddfdf3d5ab09789995869d29aaa3cd8145b32 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 26 Sep 2017 14:43:57 +0300 Subject: [PATCH] debugger agent: cache storage method --- java/debugger/impl/debugger-impl.iml | 1 - .../debugger/impl/DebuggerManagerImpl.java | 3 +- .../StackCapturingLineBreakpoint.java | 59 ++++++++++++------- 3 files changed, 38 insertions(+), 25 deletions(-) diff --git a/java/debugger/impl/debugger-impl.iml b/java/debugger/impl/debugger-impl.iml index a11386710af3..a4a7834fe605 100644 --- a/java/debugger/impl/debugger-impl.iml +++ b/java/debugger/impl/debugger-impl.iml @@ -22,7 +22,6 @@ - diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java index 8192b6d6b17c..733d3629fb1e 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java @@ -54,7 +54,6 @@ import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiClass; -import com.intellij.rt.debugger.agent.CaptureStorage; import com.intellij.util.EventDispatcher; import com.intellij.util.Function; import com.intellij.util.PathUtil; @@ -471,7 +470,7 @@ public class DebuggerManagerImpl extends DebuggerManagerEx implements Persistent ApplicationManager.getApplication().runReadAction(() -> { JavaSdkUtil.addRtJar(parameters.getClassPath()); if (Registry.is("debugger.capture.points.agent")) { - String path = PathUtil.getJarPathForClass(CaptureStorage.class); + String path = PathUtil.getJarPathForClass(DebuggerManagerImpl.class); //TODO: for now works only in debug mode String agent = "-javaagent:" + FileUtil.toSystemDependentName(PathUtil.getParentPath(PathUtil.getParentPath(path))) + diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/StackCapturingLineBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/StackCapturingLineBreakpoint.java index 05685fc49266..79d88de7a5b2 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/StackCapturingLineBreakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/StackCapturingLineBreakpoint.java @@ -35,11 +35,11 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; -import com.intellij.rt.debugger.agent.CaptureStorage; import com.intellij.ui.SimpleColoredComponent; import com.intellij.util.containers.ContainerUtil; import com.sun.jdi.*; @@ -291,30 +291,45 @@ public class StackCapturingLineBreakpoint extends WildcardMethodBreakpoint { return null; } + private static final Key> CAPTURE_STORAGE_METHOD = Key.create("CAPTURE_STORAGE_METHOD"); + public static final Pair NO_CAPTURE_AGENT = Pair.empty(); + private static List getProcessCapturedStack(Value key, EvaluationContextImpl evaluationContext) throws EvaluateException { - if (Registry.is("debugger.capture.points.agent")) { - DebugProcessImpl process = evaluationContext.getDebugProcess(); - // TODO: cache class & method - ClassType captureClass = (ClassType)process.findClass(evaluationContext, CaptureStorage.class.getName(), null); - Method getRelatedStackMethod = captureClass.methodsByName("getRelatedStack").get(0); - Value resArray = process.invokeMethod(evaluationContext, captureClass, getRelatedStackMethod, Collections.singletonList(key), true); - if (resArray instanceof ArrayReference) { - List values = ((ArrayReference)resArray).getValues(); - List res = new ArrayList<>(values.size()); - for (Value value : values) { - if (value == null) { - res.add(null); - } - else { - List values1 = ((ArrayReference)value).getValues(); - res.add(new ProcessStackFrameItem(getStringRefValue((StringReference)values1.get(0)), - getStringRefValue((StringReference)values1.get(2)), - Integer.parseInt(((StringReference)values1.get(3)).value()))); - } - } - return res; + DebugProcessImpl process = evaluationContext.getDebugProcess(); + Pair methodPair = process.getUserData(CAPTURE_STORAGE_METHOD); + if (methodPair == NO_CAPTURE_AGENT) { + return null; + } + if (methodPair == null) { + try { + ClassType captureClass = (ClassType)process.findClass(evaluationContext, "com.intellij.rt.debugger.agent.CaptureStorage", null); + Method getRelatedStackMethod = captureClass.methodsByName("getRelatedStack").get(0); + methodPair = Pair.create(captureClass, getRelatedStackMethod); } + catch (EvaluateException e) { + methodPair = NO_CAPTURE_AGENT; + LOG.debug("Error loading debug agent", e); + } + putProcessUserData(CAPTURE_STORAGE_METHOD, methodPair, process); + } + + Value resArray = process.invokeMethod(evaluationContext, methodPair.first, methodPair.second, Collections.singletonList(key), true); + if (resArray instanceof ArrayReference) { + List values = ((ArrayReference)resArray).getValues(); + List res = new ArrayList<>(values.size()); + for (Value value : values) { + if (value == null) { + res.add(null); + } + else { + List values1 = ((ArrayReference)value).getValues(); + res.add(new ProcessStackFrameItem(getStringRefValue((StringReference)values1.get(0)), + getStringRefValue((StringReference)values1.get(2)), + Integer.parseInt(((StringReference)values1.get(3)).value()))); + } + } + return res; } return null; }