2014-02-09 23 views
4

所以我試圖讓自己進入JDI。我已經成功通過第一開始與VM被調試鉤住我的調試器應用程序到我的調試者程序命令:如何設置JDI啓動連接器?

-agentlib:jdwp=transport=dt_socket,server=y,address=8000 

,然後啓動我的調試器它建立通過使用附接連接器的連接:

VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); 
AttachingConnector ac = vmm.attachingConnectors().get(0); 
Map<String, Connector.Argument> env = ac.defaultArguments(); 
env.get("port").setValue("8000"); 
env.get("hostname").setValue("localhost"); 
VirtualMachine vm = ac.attach(env); 

但現在我想讓我的調試器應用程序啓動調試程序本身。我知道在這種情況下必須使用啓動連接器。所以我試過這個:

VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); 
LaunchingConnector lc = vmm.launchingConnectors().get(0); 
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); 

但是,當我啓動這個應用程序時,我的debugee程序沒有啓動。儘管上面顯示的代碼有一堆後續代碼,但我沒有得到任何例外或任何東西,像這樣的東西:

// A single implementor of this interface exists in a particuar VM 
    EventRequestManager mgr = vm.eventRequestManager(); 

    // suspend VM 
    vm.suspend(); 

    // lookup main thread 
    ThreadReference mainThread = null; 
    List<ThreadReference> threads = vm.allThreads(); 
    for (ThreadReference thread : threads) { 
     if ("main".equals(thread.name())) { 
      mainThread = thread; 
      break; 
     } 
    } 

    // resume 
    vm.resume(); 
    mainThread.resume(); 

    // There is one instance of EventQueue assigned to a particular 
    // VirtualMachine. 
    EventQueue eventQueue = vm.eventQueue(); 

    // Waits for start event. 
    WAIT_FOR_START: do { 
     EventSet eventSet = eventQueue.remove(); 
     EventIterator eventIterator = eventSet.eventIterator(); 
     while (eventIterator.hasNext()) { 
      Event event = eventIterator.next(); 
      if (event instanceof VMStartEvent) { 
       System.out.println("VMStartEvent."); 
       break WAIT_FOR_START; 
      } 
     } 
    } while (true); 

    System.out.println("GO..."); 

這一切都運行得很好?!我沒有得到任何例外和所有系統(GO ...等)。我覺得很奇怪 - 顯然它找到了一個主線程和一個VMStartEvent。但是我想我的調試器完全是爲了自己或某個東西?恐怕我沒有真正掌握所有這些方法調用的功能。

所以我的問題:爲什麼我的debuggee程序不能啓動?

正如你可以在上面看到我做了設置「主」參數:

env.get("main").setValue("p.DebugDummy"); 

我的調試器應用程序是在同一包(P)。那應該是正確的?但顯然我在這裏做錯了什麼。有任何想法嗎?

謝謝!

回答

1

這可能是因爲你沒有處理子流程標準輸入/標準輸出流。我在我的JDI腳本項目中有一個VMLauncher實用程序類來處理這個問題;相關的代碼是:

public VirtualMachine safeStart() 
    throws IOException, 
      IllegalConnectorArgumentsException, 
      VMStartException 
{ 
    VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); 
    LaunchingConnector connector = vmm.defaultConnector(); 
    Map<String, Argument> cArgs = connector.defaultArguments(); 
    cArgs.get("options").setValue(options); 
    cArgs.get("main").setValue(main); 
    final VirtualMachine vm = connector.launch(cArgs); 

    final Thread outThread = redirect("Subproc stdout", 
             vm.process().getInputStream(), 
             out); 
    final Thread errThread = redirect("Subproc stderr", 
             vm.process().getErrorStream(), 
             err); 
    if(killOnShutdown) { 
     Runtime.getRuntime().addShutdownHook(new Thread() { 
      public void run() { 
       outThread.interrupt(); 
       errThread.interrupt(); 
       vm.process().destroy(); 
      } 
     }); 
    } 

    return vm; 
} 

private Thread redirect(String name, InputStream in, OutputStream out) { 
    Thread t = new StreamRedirectThread(name, in, out); 
    t.setDaemon(true); 
    t.start(); 
    return t; 
} 
0

你有沒有在LaunchingConnector設置CLASSPATH?

env.get("options").setValue("-cp " + 
    "/my-project/target/classes:" + 
    "/Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home/lib/tools.jar:" + 
    "");