SkyWalking Agent 与其他 Java Agent 字节码处理兼容性指南:类缓存(Class Cache)机制详解
SkyWalking Agent 与其他 Java Agent 字节码处理兼容性指南类缓存Class Cache机制详解【免费下载链接】skywalkingAPM, Application Performance Monitoring System项目地址: https://gitcode.com/gh_mirrors/sky/skywalking导读当 Java 应用同时挂载多个 Agent例如 SkyWalking Agent 与 Arthas时常常会遇到 Arthas 无法正常工作、类重转换retransform失败等问题。本篇指南以 SkyWalking 官方 FAQ 文档 Compatible-with-other-javaagent-bytecode-processing.md 为骨架深入分析该类冲突的根因并完整讲解 SkyWalking Agent 提供的类缓存Class Cache解决方案通过-Dskywalking.agent.is_cache_enhanced_class与-Dskywalking.agent.class_cache_mode两个配置项将已被增强的类字节码缓存到内存或临时文件从而与其他 Java Agent 的字节码处理流程和平共处。读完本文你将掌握该问题的成因、两种缓存模式MEMORY / FILE的区别与选择建议以及通过 JVM 参数或agent.conf两种方式启用该特性的完整实操步骤。一、问题现象多 Agent 共存时的典型冲突在 Java 应用启动时通过-javaagent方式同时挂载 SkyWalking Agent 与其他字节码处理类 Agent如 Arthas时可能出现两类典型故障其他 Agent 无法正常工作例如 Arthas 的部分命令如retransform、类增强相关操作失效或行为异常相关讨论见 apache/skywalking#4858 关联的 PR 及 issue该链接为原文档引用的外部地址仅作问题背景参考不作为本文依据。类重转换retransform失败当其他 Java Agent 对某个类执行 retransform 时与 SkyWalking Agent 发生字节码冲突表现为 retransform 不成功。官方还提供了用于复现该场景的示例项目retransform-conflict-demo原文档中给出的演示仓库仓库内未包含该示例源码此处仅保留其问题定位价值。从仓库内的版本变更记录可以确认该问题在 SkyWalking 8.1.0 时代便已进入官方视野changes-8.1.0.md 第 11 条明确写道[Core] Support instrumented class cached in memory or file, to be compatible with other agents, such as Arthas.也就是说将已增强类缓存到内存或文件以兼容其他 Agent如 Arthas正是本 FAQ 所述解决方案在官方演进史上的出处。二、根因分析ByteBuddy 随机命名辅助类与二次增强的冲突要理解冲突的根源需要先了解 SkyWalking Agent 的字节码处理机制SkyWalking Agent 使用 ByteBuddy 在 Java 应用启动阶段对目标类进行转换transform。ByteBuddy 是 Java 生态中广泛使用的字节码生成与操作库SkyWalking Agent 正是借助它来完成对业务类的插桩增强。ByteBuddy 在每次生成辅助类auxiliary class时都会使用不同的随机类名。这意味着每次对同一个类执行增强生成的字节码在字段名、辅助类名、导入的类名等方面都可能发生变化——字节码并不具备幂等性。由此推导出冲突链条对应原文档 Cause 章节的核心逻辑应用启动时SkyWalking Agent 通过 ByteBuddy 完成首轮类增强此时生成的辅助类带有随机名称当另一个 Java Agent 对同一个类执行 retransform重转换时会再次触发 SkyWalking Agent 对该类的增强流程由于字节码已由 ByteBuddy 重新生成类中的字段、辅助类名、导入类名等均已改变JVM 对类字节码的校验verification因此失败最终导致 retransform 失败。简而言之问题不在于两个 Agent 抢着改字节码本身而在于 SkyWalking Agent 二次增强时重新生成了名称随机的辅助类破坏了 JVM 校验所需的字节码一致性。三、解决方案总览启用类缓存Class Cache特性3.1 方案一通过 JVM 启动参数启用推荐用于快速验证在应用启动命令行中添加如下 JVM 参数-Dskywalking.agent.is_cache_enhanced_classtrue -Dskywalking.agent.class_cache_modeMEMORY-Dskywalking.agent.is_cache_enhanced_classtrue开启类缓存开关使 SkyWalking Agent 缓存所有已被插桩增强的类文件-Dskywalking.agent.class_cache_modeMEMORY指定缓存保存模式为内存也可设为FILE详见下文第四节。3.2 方案二通过 agent.conf 配置文件启用推荐用于长期部署SkyWalking Agent 的agent.conf中已内置了这两个配置项默认处于注释状态取消注释并设置如下即可配置项原始说明来自原文档此处保留原文语义# If true, the SkyWalking agent will cache all instrumented classes files to memory or disk files (as determined by the class cache mode), # Allow other Java agents to enhance those classes that are enhanced by the SkyWalking agent. agent.is_cache_enhanced_class ${SW_AGENT_CACHE_CLASS:false} # The instrumented classes cache mode: MEMORY or FILE # MEMORY: cache class bytes to memory; if there are too many instrumented classes or if their sizes are too large, it may take up more memory # FILE: cache class bytes to user temp folder starts with class-cache, and automatically clean up cached class files when the application exits agent.class_cache_mode ${SW_AGENT_CLASS_CACHE_MODE:MEMORY}对上述配置项的逐项说明配置项环境变量覆盖默认值作用agent.is_cache_enhanced_classSW_AGENT_CACHE_CLASSfalse是否缓存所有已被 SkyWalking Agent 增强的类字节码设为true后其他 Java Agent 才能继续增强这些类agent.class_cache_modeSW_AGENT_CLASS_CACHE_MODEMEMORY缓存保存模式MEMORY内存或FILE本地临时文件两个配置项均支持${ENV_VAR:default}形式的环境变量覆盖例如在生产环境中可以通过SW_AGENT_CACHE_CLASStrue与SW_AGENT_CLASS_CACHE_MODEFILE两个环境变量完成动态配置而无需改动agent.conf文件。3.3 缓存生效后的行为变化启用类缓存后SkyWalking Agent 的二次增强流程会发生关键变化对应原文档 Resolution 章节的说明启用后SkyWalking Agent 会将增强后的类字节码保存到内存或临时文件当其他 Java Agent 对同一类执行 retransform、再次触发 SkyWalking Agent 增强时SkyWalking Agent 会首先尝试从缓存中加载该类如果命中缓存则直接复用缓存中的字节码而不再重新生成带有新随机名称的辅助类由于字节码保持了一致性后续 Java Agent 的增强流程将不再受干扰retransform 得以成功。四、类缓存保存模式MEMORY 与 FILE 的取舍原文档明确建议优先将缓存类保存到内存。但两种模式各有适用场景选择依据如下模式设置方式保存位置优点注意事项MEMORY-Dskywalking.agent.class_cache_modeMEMORYJava 堆内存JVM 内存读写快无磁盘 IO重启即释放若被增强的类数量过多或单个类体积过大会占用较多内存FILE-Dskywalking.agent.class_cache_modeFILE以class-cache开头的用户临时目录原文档描述为 SkyWalking Agent 路径下的/class-cache几乎不占用应用内存有磁盘 IO应用退出时会自动清理缓存文件4.1 通过 JVM 参数设置模式-Dskywalking.agent.class_cache_modeMEMORY或-Dskywalking.agent.class_cache_modeFILE4.2 通过 agent.conf 设置模式在agent.conf中二选一agent.class_cache_mode ${SW_AGENT_CLASS_CACHE_MODE:MEMORY}agent.class_cache_mode ${SW_AGENT_CLASS_CACHE_MODE:FILE}4.3 选择建议默认推荐 MEMORY对于大多数应用增强类数量与体积可控内存缓存带来最低的运行时开销与最好的兼容性收益何时改用 FILE当应用被增强的类非常多、缓存字节码总体积较大、而应用内存又相对紧张时可切换为FILE模式将缓存落盘到临时目录并在应用退出时由 SkyWalking Agent 自动清理避免残留文件。五、配置验证与回退由于本仓库为只读镜像不包含可执行的 Java Agent 模块源码以下验证思路均基于官方文档描述与仓库内可确认的文档事实供你在实际部署环境中操作确认配置已生效通过jinfo -flags pid或应用启动日志查看 JVM 系统属性中是否包含skywalking.agent.is_cache_enhanced_classtrue与skywalking.agent.class_cache_mode功能验证在启用缓存后重新执行 Arthas 的retransform命令观察类重转换是否成功、目标类方法是否按预期更新回退方式如需关闭该特性移除 JVM 参数或将agent.conf中的agent.is_cache_enhanced_class恢复为false或将环境变量SW_AGENT_CACHE_CLASS设为false重启应用即可。六、结语SkyWalking Agent 与其他 Java Agent 的字节码冲突本质上是 ByteBuddy 随机命名辅助类导致二次增强字节码不一致、进而触发 JVM 校验失败的问题。通过启用类缓存特性is_cache_enhanced_classtrueclass_cache_modeSkyWalking Agent 可以在被其他 Agent 二次触发增强时复用已有字节码从源头规避冲突。该特性自 SkyWalking 8.1.0 起支持见 changes-8.1.0.md本 FAQ 是官方针对该问题给出的标准处置方案详细配置项说明与默认值请以本文第三节所引 Compatible-with-other-javaagent-bytecode-processing.md 为准。延伸阅读FAQ 索引docs/en/FAQ/README.md其中第 31 行收录了本主题条目其他 Agent 相关 FAQinstall_agent_on_websphere.mdWebSphere 场景下的 Agent 安装说明版本变更记录changes-8.1.0.md类缓存特性引入记录【免费下载链接】skywalkingAPM, Application Performance Monitoring System项目地址: https://gitcode.com/gh_mirrors/sky/skywalking创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考