使用jdi构建一个简单的调试器来设置断点并检索变量的值

我期待使用java调试接口构建调试器。
我的目标是设置断点并获取变量的值。
我发现这个答案接近我正在寻找的,我明白我必须使用以下接口: – VirtualMachineManagerLaunchingConnectorClassPrepareEventClassPrepareRequest 。 但我无法弄清楚,如何在特定行设置断点并获取变量的值或接口的使用顺序。

例如,在下面的代码中,我如何继续使用jdi运行它, jdi获得变量S的值

 import java.io.*; class Hello { public static void main(String args[]) { String S = "Hello World"; int a = 12; } } 

我正在考虑在a = 12或者在main方法结束时设置调试点,以便得到S的值

发现这篇文章很有用。 这里也是一个很好的例子 ,可以帮助你。

或者,您可以检查以下项目

这是一个供你玩的示例代码。

 /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package jdidebugger; import com.sun.jdi.AbsentInformationException; import com.sun.jdi.Bootstrap; import com.sun.jdi.ClassType; import com.sun.jdi.IncompatibleThreadStateException; import com.sun.jdi.LocalVariable; import com.sun.jdi.Location; import com.sun.jdi.Method; import com.sun.jdi.StackFrame; import com.sun.jdi.ThreadReference; import com.sun.jdi.Value; import com.sun.jdi.VirtualMachine; import com.sun.jdi.VirtualMachineManager; import com.sun.jdi.connect.Connector; import com.sun.jdi.connect.IllegalConnectorArgumentsException; import com.sun.jdi.connect.LaunchingConnector; import com.sun.jdi.connect.VMStartException; import com.sun.jdi.event.BreakpointEvent; import com.sun.jdi.event.ClassPrepareEvent; import com.sun.jdi.event.Event; import com.sun.jdi.event.EventIterator; import com.sun.jdi.event.EventQueue; import com.sun.jdi.event.EventSet; import com.sun.jdi.request.BreakpointRequest; import com.sun.jdi.request.ClassPrepareRequest; import com.sun.jdi.request.EventRequestManager; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.function.Consumer; import java.util.logging.Level; import java.util.logging.Logger; /** * * @author bonnie */ public class JdiDebugger { /** * @param options * @param main * @param classPattern * @param methodName * @param lineNumber * @throws java.io.IOException * @throws com.sun.jdi.connect.IllegalConnectorArgumentsException * @throws com.sun.jdi.connect.VMStartException * @throws java.lang.InterruptedException * @throws com.sun.jdi.AbsentInformationException * @throws com.sun.jdi.IncompatibleThreadStateException */ public static void onMethodExit(String options, String main, String classPattern, String methodName) throws IOException, IllegalConnectorArgumentsException, VMStartException, InterruptedException, AbsentInformationException, IncompatibleThreadStateException { // create and launch a virtual machine VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); LaunchingConnector lc = vmm.defaultConnector(); Map env = lc.defaultArguments(); env.get("options").setValue(options); env.get("main").setValue(main); VirtualMachine vm = lc.launch(env); // create a class prepare request EventRequestManager erm = vm.eventRequestManager(); ClassPrepareRequest r = erm.createClassPrepareRequest(); r.addClassFilter(classPattern); r.enable(); EventQueue queue = vm.eventQueue(); while (true) { EventSet eventSet = queue.remove(); EventIterator it = eventSet.eventIterator(); while (it.hasNext()) { Event event = it.nextEvent(); if (event instanceof ClassPrepareEvent) { ClassPrepareEvent evt = (ClassPrepareEvent) event; ClassType classType = (ClassType) evt.referenceType(); classType.methodsByName(methodName).forEach(new Consumer() { @Override public void accept(Method m) { List locations = null; try { locations = m.allLineLocations(); } catch (AbsentInformationException ex) { Logger.getLogger(JdiDebuggerOld.class.getName()).log(Level.SEVERE, null, ex); } // get the last line location of the function and enable the // break point Location location = locations.get(locations.size() - 1); BreakpointRequest bpReq = erm.createBreakpointRequest(location); bpReq.enable(); } }); } if (event instanceof BreakpointEvent) { // disable the breakpoint event event.request().disable(); ThreadReference thread = ((BreakpointEvent) event).thread(); StackFrame stackFrame = thread.frame(0); // print all the visible variables with the respective values Map visibleVariables = (Map) stackFrame.getValues(stackFrame.visibleVariables()); for (Map.Entry entry : visibleVariables.entrySet()) { System.out.println(entry.getKey() + ":" + entry.getValue()); } } vm.resume(); } } } } 

这就是你调用方法的方法

 new jdiDebugger().onMehtodeExit("-cp ", "", "", "");