JPDA 架構研究20 - JDI的事件請求和處理模塊

引入:java

上文主要講解了JDI的鏈接模塊來創建Debugger到Target VM之間的鏈接,這裏主要講解事件請求和處理模塊。它們都在com.sun.jdi.event和com.sun.jdi.request包中。ide


分析:this


Part 1:查看JDI中定義的事件類型spa

JDI中事件的接口叫Event . 插件

public abstract interface Event extends Mirror
{
  public abstract EventRequest request();
}

它定義了18種具體的事件類型,以下:線程

ClassPrepareEvent 裝載某個指定的類所引起的事件
ClassUnloadEvent 卸載某個指定的類所引起的事件
BreakingpointEvent 設置斷點所引起的事件
ExceptionEvent 目標虛擬機運行中拋出指定異常所引起的事件
MethodEntryEvent 進入某個指定方法體時引起的事件
MethodExitEvent 某個指定方法執行完成後引起的事件
MonitorContendedEnteredEvent 線程已經進入某個指定 Monitor 資源所引起的事件
MonitorContendedEnterEvent 線程將要進入某個指定 Monitor 資源所引起的事件
MonitorWaitedEvent 線程完成對某個指定 Monitor 資源等待所引起的事件
MonitorWaitEvent 線程開始等待對某個指定 Monitor 資源所引起的事件
StepEvent 目標應用程序執行下一條指令或者代碼行所引起的事件
AccessWatchpointEvent 查看類的某個指定 Field 所引起的事件
ModificationWatchpointEvent 修改類的某個指定 Field 值所引起的事件
ThreadDeathEvent 某個指定線程運行完成所引起的事件
ThreadStartEvent 某個指定線程開始運行所引起的事件
VMDeathEvent 目標虛擬機中止運行因此的事件
VMDisconnectEvent 目標虛擬機與調試器斷開連接所引起的事件
VMStartEvent 目標虛擬機初始化時所引起的事件


Part 2:事件集的概念調試

事件集是事件發送的最小單位,而且事件集一旦被建立,則不能夠被修改。blog

public abstract interface EventSet extends Mirror, Set<Event>
{
  public abstract int suspendPolicy();

  public abstract EventIterator eventIterator();

  public abstract void resume();
}

它也提供了迭代器來訪問事件集內的事件。接口


Part 3:事件隊列隊列

事件隊列(EventQueue)的擁有者是目標虛擬機,EventQueue 將這些事件集以「先進先出」策略依次地發送到調試器端。EventQueue 負責管理來自目標虛擬機的事件,一個被調試的目標虛擬機上有且僅有一個 EventQueue實例。特別地,隨着一次事件集的發送,目標虛擬機上可能會有一部分的線程所以而被掛起。若是一直不恢復這些線程,有可能會致使目標虛擬機掛機。


Part 4: JDI事件請求

正如Part1 所說,Event接口定義了request方法,該方法會返回由調試器Debugger發出的針對該事件的事件請求(EventRequest)。事件請求是由調試器向目標虛擬機發出的,目的是請求目標虛擬機在發生指定的事件後通知調試器。只有當調試器發出的請求與目標虛擬機上發生的事件匹配時,這些事件纔會被分發到各個事件集,進而等待發送至調試器端。

(注意:這裏可能有點繞口,一句話歸納就是 EventRequest老是由Debugger發向Target VM ,而當請求與目標虛擬機上發生事件匹配,則事件會被歸到EventSet中,EventSet會被Target VM的EventQueue所管理,而且按照FIFO原則發送到Debugger)


固然了,Debugger發送給Target VM的全部事件請求,不必定Target VM 都感興趣。所以JDI提供了事件的過濾機制,來刪選出最終真正要發送給Target VM的事件。

EventRequest中提供了一組addXXXFilter()方法來給某個事件請求添加一個或者多個過濾器:

 public void addCountFilter(int count)
    throws InvalidRequestStateException
  {
    checkDisabled();
    if (this.fCountFilters == null) {
      this.fCountFilters = new ArrayList();
    }
    this.fCountFilters.add(new Integer(count));
  }

  public void addThreadFilter(ThreadReference threadFilter)
    throws ObjectCollectedException, VMMismatchException, InvalidRequestStateException
  {
    checkVM(threadFilter);
    checkDisabled();
    if (threadFilter.isCollected())
      throw new ObjectCollectedException();
    if (this.fThreadFilters == null) {
      this.fThreadFilters = new ArrayList();
    }
    this.fThreadFilters.add(threadFilter);
  }

  public void addClassFilter(ReferenceType filter)
    throws VMMismatchException, InvalidRequestStateException
  {
    checkVM(filter);
    checkDisabled();
    if (this.fClassFilterRefs == null) {
      this.fClassFilterRefs = new ArrayList();
    }
    this.fClassFilterRefs.add(filter);
  }

  public void addClassFilter(String filter)
    throws InvalidRequestStateException
  {
    checkDisabled();
    if (this.fClassFilters == null) {
      this.fClassFilters = new ArrayList();
    }
    this.fClassFilters.add(filter);
  }

  public void addClassExclusionFilter(String filter)
    throws InvalidRequestStateException
  {
    checkDisabled();
    if (this.fClassExclusionFilters == null) {
      this.fClassExclusionFilters = new ArrayList();
    }
    this.fClassExclusionFilters.add(filter);
  }

  public void addLocationFilter(LocationImpl location)
    throws VMMismatchException
  {
    checkDisabled();

    checkVM(location);
    if (this.fLocationFilters == null) {
      this.fLocationFilters = new ArrayList();
    }
    this.fLocationFilters.add(location);
  }

  public void addExceptionFilter(ReferenceTypeImpl refType, boolean notifyCaught, boolean notifyUncaught)
    throws VMMismatchException
  {
    checkDisabled();

    if (refType != null) {
      checkVM(refType);
    }
    if (this.fExceptionFilters == null) {
      this.fExceptionFilters = new ArrayList();
    }
    ExceptionFilter filter = new ExceptionFilter();
    filter.fException = refType;
    filter.fNotifyCaught = notifyCaught;
    filter.fNotifyUncaught = notifyUncaught;
    this.fExceptionFilters.add(filter);
  }

  public void addFieldFilter(FieldImpl field)
    throws VMMismatchException
  {
    checkDisabled();

    checkVM(field);
    if (this.fFieldFilters == null) {
      this.fFieldFilters = new ArrayList();
    }
    this.fFieldFilters.add(field);
  }

  public void addStepFilter(ThreadReferenceImpl thread, int size, int depth)
    throws VMMismatchException
  {
    checkDisabled();

    checkVM(thread);

    if (this.fThreadStepFilters == null) {
      this.fThreadStepFilters = new ArrayList();
    }
    ThreadStepFilter filter = new ThreadStepFilter();
    filter.fThread = thread;
    filter.fThreadStepSize = size;
    filter.fThreadStepDepth = depth;
    this.fThreadStepFilters.add(filter);
  }

  public void addInstanceFilter(ObjectReference instance)
  {
    checkDisabled();
    checkVM(instance);
    if (this.fInstanceFilters == null) {
      this.fInstanceFilters = new ArrayList();
    }
    this.fInstanceFilters.add(instance);
  }

  public void addSourceNameFilter(String pattern)
  {
    checkDisabled();
    if (this.fSourceNameFilters == null) {
      this.fSourceNameFilters = new ArrayList();
    }
    this.fSourceNameFilters.add(pattern);
  }


Part 5: Target VM對於事件請求(EventRequest)的管理

在JDI中,事件請求的管理是經過EventRequestManager來完成的。它有許多createXXXRequest方法來建立不一樣類型的事件請求,也有許多deleteXXXRequest方法來刪除不一樣類型的事件請求,還有xxxRequests方法來列出各類類型的事件請求。

package com.sun.jdi.request;

import com.sun.jdi.Field;
import com.sun.jdi.Location;
import com.sun.jdi.Mirror;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.ThreadReference;
import java.util.List;

public abstract interface EventRequestManager extends Mirror
{
  public abstract ClassPrepareRequest createClassPrepareRequest();

  public abstract ClassUnloadRequest createClassUnloadRequest();

  public abstract ThreadStartRequest createThreadStartRequest();

  public abstract ThreadDeathRequest createThreadDeathRequest();

  public abstract ExceptionRequest createExceptionRequest(ReferenceType paramReferenceType, boolean paramBoolean1, boolean paramBoolean2);

  public abstract MethodEntryRequest createMethodEntryRequest();

  public abstract MethodExitRequest createMethodExitRequest();

  public abstract MonitorContendedEnterRequest createMonitorContendedEnterRequest();

  public abstract MonitorContendedEnteredRequest createMonitorContendedEnteredRequest();

  public abstract MonitorWaitRequest createMonitorWaitRequest();

  public abstract MonitorWaitedRequest createMonitorWaitedRequest();

  public abstract StepRequest createStepRequest(ThreadReference paramThreadReference, int paramInt1, int paramInt2);

  public abstract BreakpointRequest createBreakpointRequest(Location paramLocation);

  public abstract AccessWatchpointRequest createAccessWatchpointRequest(Field paramField);

  public abstract ModificationWatchpointRequest createModificationWatchpointRequest(Field paramField);

  public abstract VMDeathRequest createVMDeathRequest();

  public abstract void deleteEventRequest(EventRequest paramEventRequest);

  public abstract void deleteEventRequests(List<? extends EventRequest> paramList);

  public abstract void deleteAllBreakpoints();

  public abstract List<StepRequest> stepRequests();

  public abstract List<ClassPrepareRequest> classPrepareRequests();

  public abstract List<ClassUnloadRequest> classUnloadRequests();

  public abstract List<ThreadStartRequest> threadStartRequests();

  public abstract List<ThreadDeathRequest> threadDeathRequests();

  public abstract List<ExceptionRequest> exceptionRequests();

  public abstract List<BreakpointRequest> breakpointRequests();

  public abstract List<AccessWatchpointRequest> accessWatchpointRequests();

  public abstract List<ModificationWatchpointRequest> modificationWatchpointRequests();

  public abstract List<MethodEntryRequest> methodEntryRequests();

  public abstract List<MethodExitRequest> methodExitRequests();

  public abstract List<MonitorContendedEnterRequest> monitorContendedEnterRequests();

  public abstract List<MonitorContendedEnteredRequest> monitorContendedEnteredRequests();

  public abstract List<MonitorWaitRequest> monitorWaitRequests();

  public abstract List<MonitorWaitedRequest> monitorWaitedRequests();

  public abstract List<VMDeathRequest> vmDeathRequests();
}

有一點須要注意的是,這裏由EventRequestManager建立的createXXXRequest的事件都是非激活的,所以這些事件請求當發送給Target VM不會起任何做用,除非調用EventRequest的setEnable(true)使得該事件進入激活狀態。


Part 6: JDI中Debugger與Target VM之間的事件交互。

Step 1:Debugger調用Target VM的 eventQueue() 和 eventRequestManager() 分別獲取惟一的 EventQueue 實例和 EventRequestManager 實例.


Step 2: Debugger經過 EventRequestManager 的 createXXXRequest() 建立須要的事件請求,並添加過濾器和設置掛起策略.

Step 3: Debugger經過EventQueue 獲取來自Target VM的事件實例.

這個事件實例包含了許多信息,好比ThreadReference ,StackFrame,LocalVariable, Location,Method等,這些事件信息就包含了當前Target VM的一些現有狀態信息和數據,Debugger就用這些數據交給Eclipse的相應的Debugger UI插件來顯示結果。


總結:

在此文章中,咱們涉及到了多個概念,這裏把其中的類模型歸納下:

wKiom1SGzHigR1adAAFDI0xXU0I825.jpg

相關文章
相關標籤/搜索