skywalking 插件加载流程

插件加载流程

入口: PluginBootstrap#loadPlugins

# 处理化 ClassLoader
AgentClassLoader.initDefaultLoader();

PluginResourcesResolver resolver = new PluginResourcesResolver();
# 读取所有 jar 包, 读取 skywalking-plugin.def 文件内容
List<URL> resources = resolver.getResources();

if (resources == null || resources.size() == 0) {
    LOGGER.info("no plugin files (skywalking-plugin.def) found, continue to start application.");
    return new ArrayList<AbstractClassEnhancePluginDefine>();
}

for (URL pluginUrl : resources) {
    try {
        // 解析 skywalking-plugin.def 文件内容, 转换为 List<PluginDefine>
        // 内容格式 name(插件名称)=defineClass(对应类)
        PluginCfg.INSTANCE.load(pluginUrl.openStream());
    } catch (Throwable t) {
        LOGGER.error(t, "plugin file [{}] init failure.", pluginUrl);
    }
}

List<PluginDefine> pluginClassList = PluginCfg.INSTANCE.getPluginClassList();

List<AbstractClassEnhancePluginDefine> plugins = new ArrayList<AbstractClassEnhancePluginDefine>();
for (PluginDefine pluginDefine : pluginClassList) {
    try {
        // 类初始化
        AbstractClassEnhancePluginDefine plugin = (AbstractClassEnhancePluginDefine) Class.forName(pluginDefine.getDefineClass(), true, AgentClassLoader
            .getDefault()).newInstance();
        plugins.add(plugin);
    } catch (Throwable t) {
        LOGGER.error(t, "load plugin [{}] failure.", pluginDefine.getDefineClass());
    }
}

plugins.addAll(DynamicPluginLoader.INSTANCE.load(AgentClassLoader.getDefault()));

return plugins;

扫描所有 jar 包的流程在 AgentClassLoader#findResource 方法中

@Override
protected URL findResource(String name) {
    // 获取到 agent plugin 目录下所有的jar包
    List<Jar> allJars = getAllJars();
    for (Jar jar : allJars) {
        JarEntry entry = jar.jarFile.getJarEntry(name);
        if (entry != null) {
            try {
                return new URL("jar:file:" + jar.sourceFile.getAbsolutePath() + "!/" + name);
            } catch (MalformedURLException ignored) {
            }
        }
    }
    return null;
}

字节码增强

SkyWalkingAgent#premain

// 预处理, 屏蔽包
 final ByteBuddy byteBuddy = new ByteBuddy().with(TypeValidation.of(Config.Agent.IS_OPEN_DEBUGGING_CLASS));
AgentBuilder agentBuilder = new AgentBuilder.Default(byteBuddy).ignore(
                nameStartsWith("net.bytebuddy.")
                .or(nameStartsWith("org.slf4j."))
                .or(nameStartsWith("org.groovy."))
                .or(nameContains("javassist"))
                .or(nameContains(".asm."))
                .or(nameContains(".reflectasm."))
                .or(nameStartsWith("sun.reflect"))
                .or(allSkyWalkingAgentExcludeToolkit())
                .or(ElementMatchers.isSynthetic()));

// 应用到 instrumentation
// type 设置匹配
agentBuilder.type(pluginFinder.buildMatch())
            // 使用插件对应的类来增强
            .transform(new Transformer(pluginFinder))
            .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
            // 设置监听器, 针对完整的增强行为
            .with(new RedefinitionListener())
            // 针对每个类的监听
            .with(new Listener())
            .installOn(instrumentation);

ByteBuddy使用入坑

调用链

  1. SkyWalkingAgent.Transformer#transform
for (AbstractClassEnhancePluginDefine define : pluginDefines) {
    DynamicType.Builder<?> possibleNewBuilder = define.define(
            typeDescription, newBuilder, classLoader, context);
    if (possibleNewBuilder != null) {
        newBuilder = possibleNewBuilder;
    }
}
  1. AbstractClassEnhancePluginDefine#define
  2. AbstractClassEnhancePluginDefine#enhance
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;
}
  1. 类增强 ClassEnhancePluginDefineV2#enhanceClass
# 这里只有其中一段, 就是通过对象增强静态方法
newClassBuilder = newClassBuilder.method(
    isStatic()
    .and(staticMethodsInterceptV2Point.getMethodsMatcher())) 
    .intercept(MethodDelegation.withDefaultConfiguration()          
    .to(new StaticMethodsInterV2WithOverrideArgs(interceptor)));
  1. 实例增强 ClassEnhancePluginDefineV2#enhanceInstance
ElementMatcher.Junction<MethodDescription> junction = not(isStatic()).and(instanceMethodsInterceptV2Point.getMethodsMatcher());
if (instanceMethodsInterceptV2Point instanceof DeclaredInstanceMethodsInterceptV2Point) {
    junction = junction.and(ElementMatchers.<MethodDescription>isDeclaredBy(typeDescription));
}
...
newClassBuilder = newClassBuilder.method(junction)        
    .intercept(MethodDelegation.withDefaultConfiguration()
    .withBinders(Morph.Binder.install(OverrideCallable.class))     
    .to(new InstMethodsInterV2WithOverrideArgs(interceptor, classLoader)));
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容