Как можно отследить рекурсивные вызовы, используя интерфейс отладки Java? - PullRequest
1 голос
/ 07 июня 2019

Как можно использовать Java Debug Interface для отслеживания рекурсивных вызовов, которые, вероятно, будут сделаны при оценке выражения Main.reverseString ( args[0] ) в файле Main.java?

Вот файл Main.java:

public class Main
  {
  public static void main ( String [] args )
    {
    System.out.println ( "args[0] ..... " + args[0] ) ;
    String reversed = Main.reverseString ( args[0] ) ;
    System.out.println ( "reversed .... " + reversed ) ;
    } // main
  public static String reverseString ( String s )
    {
    if ( s.length() <= 1 )
      return s ;
    return ( (new StringBuilder(reverseString(s.substring(1))))
                              .append(s.charAt(0)).toString() ) ;
    } // reverseString
  } // Main

Моя программа трассировки (RecursionTracer) показана ниже:

import com.sun.jdi.* ;
import com.sun.jdi.connect.* ;
import com.sun.jdi.request.* ;
import com.sun.jdi.event.* ;
import java.util.* ;

public class RecursionTracer
  {
  public static void main ( String [] args ) throws Exception
    {
    LaunchingConnector launchingConnector
      =  Bootstrap.virtualMachineManager().defaultConnector() ;
    Map<String, Connector.Argument> env
      =  launchingConnector.defaultArguments() ;
    env.get("main").setValue ( Main.class.getName() ) ;
    VirtualMachine vm = launchingConnector.launch(env) ;

    ClassPrepareRequest classPrepareRequest
      =  vm.eventRequestManager().createClassPrepareRequest() ;
    classPrepareRequest.addClassFilter ( Main.class.getName() ) ;
    classPrepareRequest.enable() ;

    EventSet eventSet = null ;
    do
      {
      eventSet = vm.eventQueue().remove() ;
      for ( Event event : eventSet )
        {
        if ( event instanceof ClassPrepareEvent )
          {
          MethodEntryRequest methodEntryRequest
            =  vm.eventRequestManager().createMethodEntryRequest() ;
          methodEntryRequest.addClassFilter ( Main.class.getName() ) ;
          methodEntryRequest.enable() ;
          } // if ClassPrepareEvent

        if ( event instanceof MethodEntryEvent )
          {
          System.out.println ( "\n--------------------------------------" ) ;
          MethodEntryEvent methodEntryEvent = (MethodEntryEvent) event ;
          com.sun.jdi.Method method = methodEntryEvent.method () ;
          System.out.println ( "MethodEntryEvent has occurred ..." ) ;
          System.out.println ( methodEntryEvent ) ;
          System.out.println ( method ) ;
          System.out.println ( "======================================\n" ) ;
          } // if MethodEntryEvent

        vm.resume() ;
        } // for each event
      }
    while ( eventSet != null ) ;
    } // main
  } // RecursionTracer

Я компилирую Main.java и RecursionTracer.java следующим образом:

del *.class
D:\Java\JDK-11~1.1\bin\javac.exe -g Main.java RecursionTracer.java -Xlint:unchecked

Когда я запускаю RecursionTracer, его вывод:

D:\>D:\Java\JDK-11~1.1\bin\java.exe RecursionTracer

--------------------------------------
MethodEntryEvent has occurred ...
MethodEntryEvent@Main:5 in thread main
Main.main(java.lang.String[])
======================================

Exception in thread "main" com.sun.jdi.VMDisconnectedException
    at jdk.jdi/com.sun.tools.jdi.EventQueueImpl.removeUnfiltered(EventQueueImpl.java:200)
    at jdk.jdi/com.sun.tools.jdi.EventQueueImpl.remove(EventQueueImpl.java:97)
    at jdk.jdi/com.sun.tools.jdi.EventQueueImpl.remove(EventQueueImpl.java:83)
    at RecursionTracer.main(RecursionTracer.java:26)

Я ожидал, что MethodEntryEvent s будет происходить каждый раз, когда вводится метод Main.reverseString, но, как видно из вышеприведенного вывода, единственный MethodEntryEvent - это когда выполнение входит в Main.main. Почему также не отображается MethodEntryEvent s для Main.reverseString? Кроме того, как я могу получить такие MethodEntryEvent с для отображения? Наконец, было бы неплохо увидеть аргумент, который передается Main.reverseString при каждом вызове этого метода.

1 Ответ

0 голосов
/ 07 июня 2019

Вы не видите никаких других методов, потому что ваш код не делает никаких вызовов методов - вместо этого он получает ArrayIndexOutOfBoundsException в самой первой строке метода main, так как вы не передаете никаких аргументов вашему main метод.

Простое решение состоит в том, чтобы изменить ваш метод main и добавить его в самой первой строке:

args = new String[]{ "foobar"};

это даст что-то вспять. Должен быть способ передачи аргументов при запуске JRE с использованием LaunchingConnector.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...