Why method breakpoints are so slow

Some IDEs provide the "method breakpoint" function, which can make breakpoint debugging look very simple. However, during the debugging process, we will find that the debugging response time is very long, and the performance of the debugger is greatly reduced. In this article, I will briefly explain how method breakpoints are implemented and why they lead to poor performance.

For a better understanding, let me briefly explain how breakpoints are implemented and how the debugger works.

JPDA(Java Platform Debugger Architecture)

JPDA is a JAVA debugging framework, mainly used for communication between debugger (debugger) and debuggee (debugger or process). JPDA mainly consists of three main APIs.

  1. JVM TI (JVM Tool Interface): A native interface that defines the functions that the VM provides for debugging.
  2. Java Debug Wire Protocol (JDWP): JDWP is an Api that defines debugger and debuggee communication.
  3. Java Debug Interface (JDI): Java interface, used for communication and interaction between the front end and the back end, JDI internally implements the JDWP interface.
  4. The back-end and font-end in the figure below and in the article refer to the debugger (process) and editor running on the VM respectively.

  5. Debugging chain: When related events occur (such as breakpoints, single-step debugging, parameter value modification during debugging), the VM calls JVM TI through callbacks (JNI: java Native Interface, VM calls Native Interface through JNI), and then back-end Send event to font-end. The debugger communicates with the backend via JDI and JDWP.

Why use method breakpoints

If the called method cannot access the source code, or there are multiple if exits in the method, it is very simple to use method breakpoints at this time.

JAVA breakpoint principle

Make a breakpoint in the editor, often three steps will be performed internally

  1. Allow breakpoint events: The VM allows the debugger to activate various events. The font-end call  SetEventNotificationMode() method is enabled  can_generate_breakpoint_events . When running to a breakpoint, the VM will trigger an event and return a value through the debugger chain.
  2. SetBreakpoint Register breakpoints: Set breakpoints through  methods. When a thread runs to a breakpoint, the VM will suspend all active threads and trigger a breakpoint event.
    SetBreakpoint(jvmtiEnv* env,
    
                  jmethodID method, //注意一下此变量,下文会再次提到。
    
                  jlocation location)
    
  3. Breakpoint event: The event triggered by the VM is called a breakpoint event, which is used to notify the debugger. event: Breakpoint(xxx)

method breakpoint

In fact, JDPA does not provide the function of method breakpoints, method breakpoints are provided by the editor.

The debugger calls the above mentioned  SetEventNotificationMode(),
enable  can_generate_method_entry_events and  can_generate_method_exit_eventswhen the VM runs the entry and exit methods, it will send the method entry and exit events to the debugger:

MethodEntry(....,JmethodID method)
MethodExit(....,JmethodID method)

Breakpoint implementation process:

  1. The IDE adds the breakpoint to a breakpoint list maintained in the editor.
  2. The debugger calls the above-mentioned SetEventNotificationMode(), enables entry events and exit events, and sends events to the debugger when the VM runs the code to enter and exit the method.
  3. Whenever a method is entered and exited, the VM sends a MethodEntry or MethodExit to font-end.
  4. The IDE retrieves whether the id exists in the breakpoint list according to the jmethodID in the event.
  5. If it exists, the debugger calls  SetBreakPoint the method, sending the request to the VM.
  6. The VM runs the code to the breakpoint, stops the active thread, and returns the event to the debugger

The difference from ordinary breakpoints is that method breakpoints need to first determine whether the method is marked by the front end as a breakpoint in the process, and then register the breakpoint.

Why is the debug method breakpoint so slow

  1. JmethodID: JmethodID is the identifier of the running method. Every time the VM needs to return MethodEntry and MethodExit, it needs to carry the JmethodID. However, it takes a long time for the VM to search and obtain the JmethodID.
  2. communication: methodEntry and MethodExit cause a lot of communication round trips between the frontend and the backend.
  3. VM callback is synchronization: When a VM triggers an event and uses a callback, it goes through the following steps (all are synchronous operations):
    1. Switch context to back-end, back-end informs font-end
    2. According to the returned jmethodID, font-end finds whether it exists in the breakpoint list.
      Code execution is suspended during this time.

Summarize

  1. Minimize the use of method breakpoints.
  2. If it is not necessary, you can only use methodEntry, do not activate methodExit, and reduce the number of searches and communications.

 

Guess you like

Origin blog.csdn.net/weixin_47367099/article/details/127536392