本文基于 SkyWalking-Java-agent 8.15.0 版本
AbstractClassEnhancePluginDefine:所有插件的基础抽象类。它提供增强类的框架,需要了解更多增强信息可以查看 ClassEnhancePluginDefine
/**
* witness机制校验当前插件是否可用
* 调用enhance()方法进行字节码增强流程
* 将记录状态的上下文EnhanceContext设置为已增强
*
* Main entrance of enhancing the class.
*
* @param typeDescription target class description.
* @param builder byte-buddy's builder to manipulate target class's bytecode.
* @param classLoader load the given transformClass
* @return the new builder, or <code>null</code> if not be enhanced.
* @throws PluginException when set builder failure.
*/
public DynamicType.Builder<?> define(TypeDescription typeDescription, DynamicType.Builder<?> builder,
ClassLoader classLoader, EnhanceContext context) throws PluginException {
// 当前插件的全类名
String interceptorDefineClassName = this.getClass().getName();
// 当前被拦截到的类的全类名
String transformClassName = typeDescription.getTypeName();
if (StringUtil.isEmpty(transformClassName)) {
LOGGER.warn("classname of being intercepted is not defined by {}.", interceptorDefineClassName);
return null;
}
LOGGER.debug("prepare to enhance class {} by {}.", transformClassName, interceptorDefineClassName);
// witness机制校验当前插件是否可用
WitnessFinder finder = WitnessFinder.INSTANCE;
/**
* find witness classes for enhance class
*/
String[] witnessClasses = witnessClasses();
if (witnessClasses != null) {
for (String witnessClass : witnessClasses) {
// 代码1)判断 witnessClass 是否存在
if (!finder.exist(witnessClass, classLoader)) {
LOGGER.warn("enhance class {} by plugin {} is not activated. Witness class {} does not exist.", transformClassName, interceptorDefineClassName, witnessClass);
return null;
}
}
}
List<WitnessMethod> witnessMethods = witnessMethods();
if (!CollectionUtil.isEmpty(witnessMethods)) {
for (WitnessMethod witnessMethod : witnessMethods) {
// 代码2)判断 witnessMethod 是否存在
if (!finder.exist(witnessMethod, classLoader)) {
LOGGER.warn("enhance class {} by plugin {} is not activated. Witness method {} does not exist.", transformClassName, interceptorDefineClassName, witnessMethod);
return null;
}
}
}
/**
* 字节码增强流程
* find origin class source code for interceptor
*/
DynamicType.Builder<?> newClassBuilder = this.enhance(typeDescription, builder, classLoader, context);
// 将记录状态的上下文EnhanceContext设置为已增强
context.initializationStageCompleted();
LOGGER.debug("enhance class {} by {} completely.", transformClassName, interceptorDefineClassName);
return newClassBuilder;
}
类增强操作:
protected DynamicType.Builder<?> enhance(TypeDescription typeDescription, DynamicType.Builder<?> newClassBuilder,
ClassLoader classLoader, EnhanceContext context) throws PluginException {
// 静态方法插桩
newClassBuilder = this.enhanceClass(typeDescription, newClassBuilder, classLoader);
// 构造器和实例方法插桩
newClassBuilder = this.enhanceInstance(typeDescription, newClassBuilder, classLoader, context);
return newClassBuilder;
}
protected abstract DynamicType.Builder<?> enhanceInstance(TypeDescription typeDescription,
DynamicType.Builder<?> newClassBuilder, ClassLoader classLoader,
EnhanceContext context) throws PluginException;
/**
* 静态方法插桩
* 1、获取静态方法拦截点
* 2、根据是否要修改原方法入参和是否为JDK类库的类走不通的分支处理逻辑
*/
protected abstract DynamicType.Builder<?> enhanceClass(TypeDescription typeDescription, DynamicType.Builder<?> newClassBuilder,
ClassLoader classLoader) throws PluginException;
Witness 机制
作用:识别组件版本
- witnessClasses:在指定类加载器下查找指定的类,如果有多个类则必须同时存在
- witnessMethods:在指定类加载器下查找指定的方法,如果有多个方法则必须同时存在
工作流程
校验 TypeDescription 的合法性
witness 机制校验当前插件是否可用
字节码增强流程
静态方法
- 要修改原方法入参
- 是JDK类库的类
- 不是JDK类库的类
- 实例化插件中定义的 Interceptor
- 调用 beforeMethod()
- 调用原方法
- 调用时可以传参
- 对于异常,调用 handlerMethodException()
- 调用 afterMethod()
- 不修改原方法入参
- 是JDK类库的类
- 前置工作:使用对应的 Template 生成实际使用的拦截逻辑,即 Xxx_internal
- 调用 prepare()
- 打通 BootstrapClassLoader 和 AgentClassLoader
- 通过AgentClassLoader加载,拿到日志对象 ILog
- 通过AgentClassLoader加载,实例化插件定义的拦截器
- 后续流程和非 JDK 核心类库处理流程一致
- 不是JDK类库的类
- 实例化插件中定义的 Interceptor
- 调用 beforeMethod()
- 调用原方法
- 调用时不能传参
- 对于异常,调用 handlerMethodException()
- 调用 afterMethod()
构造器和实例方法
- 构造器
- 是JDK类库的类
- 不是JDK类库的类
- 只能在拦截的构造器原本逻辑执行完以后再执行 onConstruct
- 实例方法(参照静态方法)