前文忘了提到,源码版本3.5.1。 如果有任何纰漏欢迎指出。
目录
1 SpyInterceptors
Arthas中所有的切面拦截都是在SpyInterceptors的内部类中,9个内部类可以分为三类,分别是拦截目标方法的SpyInterceptor内部类、拦截目标方法内部子调用(包括JDK的子调用)的SpyTraceInterceptor内部类、拦截目标方法内部子调用(不包含所有JDK的子调用)的SpyTraceExcludeJDKInterceptor内部类,类图如下所示。
所有内部类当中有且只有一个静态方法,每个静态方法都会调用SpyAPI这个类中对应的静态方法。所以这九个类中的九个静态方法,是用来增强到目标方法切面的,而每个切面具体执行的代码还要看SpyAPI里的代码。
2 SpyAPI
SpyAPI的类图如下图所示。
SpyAPI当中的6个“at…”静态方法都调用了实例spyInstance中对应的方法。spyInstance的静态类型是抽象类AbstractSpy,抽象类AbstractSpy当中有六个抽象方法。当SpyAPI被加载时,它的静态语句会将spyInstance设置为类NopSpy的实例,其中这NopSpy继承自AbstractSpy并且实现的每个方法都是空操作。
当加载类Enhancer的时候会有一条静态语句来初始化SpyAPI,如下。代码当中的SpyImpl也是继承自AbstractSpy,经此,切面拦截时将调用类SpyImpl中对应的方法,下一节接着SpyImpl看。
private static SpyImpl spyImpl = new SpyImpl();
static {
SpyAPI.setSpy(spyImpl);
}
另外,需要说明的是,为何SpyAPI的包名是以java开头,并且要在ArthasBootstrap单例初始化的时候将其附加到引导类加载器,就是为了能够让所有的Class都能够让SpyAPI中的静态方法能够被任意类调用。如果SpyAPI是由ArthasClassLoader加载,那么其父加载器ExtClassLoader加载的类就无法调用SpyAPI中的方法,最直接的影响就是AppClassLoader加载的类都无法调用SpyAPI。
3 SpyImpl
SpyImpl的类图如下,没有多少看头。
六个“at…”方法中每个方法的逻辑都是一样的,以atEnter为例代码如下。
@Override
public void atEnter(Class<?> clazz,