前文忘了提到,源码版本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
pub

本文详细分析了Arthas的类增强过程,从SpyInterceptors的内部类结构到SpyAPI的静态方法,再到SpyImpl的实现和AdviceListenerManager的监听器管理。重点讲解了Enhancer如何在方法调用时进行增强,并注册监听器,以及TransformerManager如何统一管理ClassFileTransformer。整个流程展示了Arthas如何实现对目标类和方法的动态拦截和增强。
——类增强&spm=1001.2101.3001.5002&articleId=119877079&d=1&t=3&u=6a569dfed3d24ef5a52fc17e820a5cb1)
891

被折叠的 条评论
为什么被折叠?



