Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to abort long running invokeMethod on com.sun.jdi.ObjectReference?

I have my own JDI Debugger which calls the toString method on some objects:

com.sun.jdi.ObjectReferenceobject object = ...
ThreadReference threadRef = frameProxy.threadProxy().getThreadReference();
Value value = object.invokeMethod(threadRef, toStringMethod,
                    Collections.EMPTY_LIST, ObjectReference.INVOKE_SINGLE_THREADED);

The problem is that even if no breakpoints are set inside the toString() method, the invokeMethod never terminates so my debugger hangs. For example this happens when I call this on a Double object.

How can I kill the execution of invokeMethod after some duration of time?

Update: I tried implementing my own Double object and put some System.out.println() statements at the start and end of the toString() method and it seemed that the method is executed just fine but for some reason the debugger doesn't receive the result. Maybe this is a bug in JDI because there are many such bugs, but I am not looking for a solution for this, I am just looking for a way to abort the execution of invokeMethod() if it takes too much time.

Update2: I tried what ThierryB was suggesting but I can only invoke frameProxy.threadProxy().stop(object); in the manager thread. And the manager thread is blocked because of invokeMethod() so it won't execute my command. I tried something like this:

boolean[] isFinished = new boolean[2];
isFinished[0] = false;

DebuggerManagerThreadImpl managerThread = debugProcess.getManagerThread();
new Thread(() - > {
    try {
        Thread.sleep(2000);
        if (!isFinished[0]) {
            System.out.println("Invoked");
            managerThread.invokeCommand(new DebuggerCommand() {
                @Override
                public void action() {
                    try {
                        frameProxy.threadProxy().stop(object);
                    } catch (InvalidTypeException e) {
                        e.printStackTrace();
                    }
                    int threadStatus = frameProxy.threadProxy().status();
                    switch (threadStatus) {
                        case ThreadReference.THREAD_STATUS_RUNNING:
                            System.out.println("The thread is running.");
                            break;
                        case ThreadReference.THREAD_STATUS_ZOMBIE:
                            System.out.println("The thread has been completed.");
                            break;
                        case ThreadReference.THREAD_STATUS_WAIT:
                            System.out.println("The thread is waiting.");
                            break;
                        default:
                            System.out.println("The thread is not running / not waiting / not completed : but what is it doing right now ? (a little programmer joke ;) )");
                    }
                }

                @Override
                public void commandCancelled() {

                }
            });
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}).start();

Value value = object.invokeMethod(threadRef, toStringMethod,
    Collections.EMPTY_LIST, ObjectReference.INVOKE_SINGLE_THREADED);

isFinished[0] = true;

but frameProxy.threadProxy().stop(object); is never executed because the DebuggerCommand's action method is not called(thread is blocked).

Also this is a Stack trace when my Debugger hangs and I forcefully stop the process:

com.sun.jdi.VMDisconnectedException
    at com.jetbrains.jdi.TargetVM.waitForReply(TargetVM.java:317)
    at com.jetbrains.jdi.VirtualMachineImpl.waitForTargetReply(VirtualMachineImpl.java:1170)
    at com.jetbrains.jdi.PacketStream.waitForReply(PacketStream.java:86)
    at com.jetbrains.jdi.JDWP$ObjectReference$InvokeMethod.waitForReply(JDWP.java:4840)
    at com.jetbrains.jdi.ObjectReferenceImpl.invokeMethod(ObjectReferenceImpl.java:413)

UPDATE 3: which thread to use to invoke the Method? Currently I am using frameProxy.threadProxy().getThreadReference(); which works fine most of the time, but is it better to create a separate thread just for invoking methods on objects(along my JDI debugger I also have an instrumentation agent inside the application so I can create a separate thread just for this use case (maybe this will prevent deadlocks?)).

UPDATE 4: Currently I am using SUSPEND_ALL as suspend policy, would it be better to use SUSPEND_EVENT_THREAD instead?

like image 687
Nfff3 Avatar asked Aug 17 '20 21:08

Nfff3


Video Answer


1 Answers

You can use the interface ThreadReference with the method void stop(ObjectReference throwable). The javadoc api tells "Stops this thread with an asynchronous exception.".

try {
    com.sun.jdi.ObjectReferenceobject object = ...
    ThreadReference threadRef = frameProxy.threadProxy().getThreadReference();
    frameProxy.threadProxy().stop(object);
    int threadStatus = frameProxy.threadProxy().status();
    switch(threadStatus) {
         case ThreadReference.THREAD_STATUS_RUNNING :
              log.info("The thread is running.");
              break;
         case ThreadReference.THREAD_STATUS_ZOMBIE :
              log.info("The thread has been completed.");
              break;
         case ThreadReference.THREAD_STATUS_WAIT :
              log.info("The thread is waiting.");
              break;
         default :
              log.info("The thread is not running / not waiting / not completed : but what is it doing right now ? (a little programmer joke ;) )");
    }
} catch (ClassNotLoadedException cnle) {
    // log exception, or display a message...
} catch (IncompatibleThreadStateException itse) {
    // log exception, or display a message...
} catch (InvalidTypeException ite) {
    // log exception, or display a message...
}

When you are checking your thread status with the status method, you can find that values :

  • THREAD_STATUS_UNKNOWN
  • THREAD_STATUS_ZOMBIE
  • THREAD_STATUS_RUNNING
  • THREAD_STATUS_SLEEPING
  • THREAD_STATUS_MONITOR
  • THREAD_STATUS_WAIT
  • THREAD_STATUS_NOT_STARTED

Hope you will find a way to do what you need to with the stuff I have provided here. Examples from here or the following suite test published on the website of Alvin Alexander could be helpfull too.

like image 169
BendaThierry.com Avatar answered Sep 25 '22 22:09

BendaThierry.com