Search code examples
javadebuggingjdi

Java JDI CommandLineLaunch Not Loading Desired Class


I'm currently learning Java's JDI and I'm trying to launch a Virtual Machine that is running my desired program and establish a connection to the launched VM which is running the desired program.

In order to this, I am using a Launching connector ("com.sun.jdi.CommandLineLaunch").

I give the launching connector the following arguments:

        LaunchingConnector connector = findConnecter();
        Map args = connector.defaultArguments();

        //Main Arguments
        Connector.Argument mainArgs = (Connector.Argument)args.get("main");
        mainArgs.setValue("Main2");

        //Options Arguments
        Connector.Argument options = (Connector.Argument)args.get("options");
        options.setValue("-cp .");

Then launch the connector with VirtualMachine vm = connector.launch(args);. However, when I print out a list of classes loaded using the following code fragment:

            List<ReferenceType> classes = vm.allClasses();
            for (int i = 0; i<classes.size(); i++){
                System.out.println(classes.get(i).name());
            }

The Main2 class is not in the list.

I'm guessing its a class path issue but could not get this to work. The Main2.class file is in the same directory as the class where the above code resides.

Anyone know what the issue is?


Solution

  • The Main class is not loaded initially due to the VM suspending just before it gets loaded.

    In order to get notifications of classes being loaded, you need to create 'ClassPrepareRequest' and enable it. Then process the launched VM's 'EventQueue' as events arrive. Some events cause the VM to suspend, so must call vm.resume() after.

    Example processing:

    while (true) {
        //Waits forever for the next available event. Pauses here until something is available.
                 EventSet eventSet = eventQ.remove();
                 for(Event event: eventSet){
                           if(event instanceof ClassPrepareEvent){
                                ClassPrepareEvent classPrepareEvent = (ClassPrepareEvent)event;
                                ReferenceType refType = classPrepareEvent.referenceType();
                                System.out.println("---"+refType.name() + " loaded.");
                            }
                   vm.resume()
                 }
    }