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

相关文章
相关标签/搜索