2016-02-15 52 views
1

我想在应用程序开始运行之前设置一个断点,这样我就可以确保应用程序在启动时不会传递断点。如何在执行前设置断点

为了设置你需要做的是这样一个断点:

EventRequestManager reqMan = vm.eventRequestManager(); 
BreakpointRequest bpReq = reqMan.createBreakpointRequest(locationForBreakpoint); 
bpReq.enable(); 

为了获得断点的位置,你可以这样做:

Method method = location.method(); 
List<Location> locations = method.locationsOfLine(55); 
Location locationForBreakpoint = locations.get(0); 

为了得到一个方法,你可以这样做:

classType.concreteMethodByName(methodNname, String signature) 

不过,为了得到那个classTyp您似乎需要一个似乎需要运行JVM的ObjectReference。

有没有什么办法在应用程序JVM运行之前设置断点,以确保在应用程序启动过程中不会传递断点?

回答

1

首先使用LaunchingConnector开始您的目标程序以获取目标虚拟机。

VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); 
LaunchingConnector lc = vmm.launchingConnectors().get(0); 
// Equivalently, can call: 
// LaunchingConnector lc = vmm.defaultConnector(); 

Map<String, Connector.Argument> env = lc.defaultArguments(); 
env.get("main").setValue("p.DebugDummy"); 
env.get("suspend").setValue("true"); 
env.get("home").setValue("C:/Program Files/Java/jdk1.7.0_51"); 
VirtualMachine vm = lc.launch(env); 

(根据您的需求变化的环境值,但记得要启动目标VM与suspended=true)。
有了这个虚拟机,你可以使用ClassPrepareRequest来拦截ClassPrepareEvent

ClassPrepareRequest r = reqMan.createClassPrepareRequest(); 
r.addClassFilter("myclasses.SampleClass"); 
r.enable(); 

创建ClassPrepareEvent处理

executor.execute(()-> { 
    try { 
     while(true) 
     { 
      EventQueue eventQueue = vm.eventQueue(); 
      EventSet eventSet = eventQueue.remove(); 
      EventIterator eventIterator = eventSet.eventIterator(); 
      if (eventIterator.hasNext()) { 
      Event event = eventIterator.next(); 
      if(event instanceof ClassPrepareEvent) { 
       ClassPrepareEvent evt = (ClassPrepareEvent) event; 
       ClassType classType = (ClassType) evt.referenceType(); 
       List<Location> locations = referenceType.locationsOfLine(55); 
       Location locationForBreakpoint = locations.get(0); 

       vm.resume(); 
      } 
      } 
     } 
    } catch (InterruptedException | AbsentInformationException | IncompatibleThreadStateException e) { 
     e.printStackTrace(); 
    } 
    } 

然后调用恢复目标VM vm.resume()运行程序。 我希望这能解决你的问题。

+0

听起来很有希望,但你能否详细说明,我没有看到从ClassPrepareRequest到断点的文档。 –

+0

活动从哪里来? –

+0

来自EventRequestManager。类准备的请求具有与其他任何请求相同的创建模式(如您的示例中的断点)。当准备好类时(例如从类加载器加载)一个ClassPrepareEvent被触发;拦截并创建断点请求 –