Java ASM 与运行时字节码织入

背景 BTrace、Arthas、Spring LTW、部分 AOP 框架都会在不改变业务源码的前提下改写字节码。底层常依赖 ASM(或其它字节码库)配合 JVM 的 java.lang.instrument API。 本文说明 ASM 做什么、运行时织入怎么走,以及与 Attach API / Agent 的关系。BTrace 的 attach 与脚本下发见 BTrace。概念总图见 Java 领域知识关系图。ClassLoader 可见性见 java classloader。 JLS 与 java.lang.instrument 分别指什么 JLS(Java Language Specification):Java 语言规范,定义语法、类型、可见性等;不规定 Agent 怎么 attach。 java.lang.instrument:JDK 里的标准 API 包,定义 Instrumentation、ClassFileTransformer,以及 Agent 入口约定(premain / agentmain 的方法签名、manifest 的 Premain-Class / Agent-Class)。 日常说「走 instrument 机制」= 用这套 API + JVM 内置实现,在类加载或 retransform 时回调你的 transformer。 Agent 框架定义了什么、解决什么问题 Agent 不是一个限制能力的沙箱,而是一套标准钩子 + 能力接口: 约定 / 能力 作用 manifest Agent-Class / Premain-Class 告诉 JVM 加载 agent 后调用哪个类的哪个入口 agentmain / premain + Instrumentation 在 JVM 启动后或 attach 后执行你的初始化逻辑 ClassFileTransformer 在类字节码进入 JVM 前(或 retransform 时)允许你替换字节码 Attach API loadAgent 运行中的 JVM 也能挂上 agent 要解决的问题:在不重启、不改磁盘上已部署 jar 的前提下,对已在内存中的类做字节码级增强(监控、诊断、部分场景下的热修复)。 ...

Created 15156-12-15 · Updated 30306-06-30 · 3 min · 580 words · -

Java Attach API

背景 JDK 8 生产排查里,BTrace、jcmd 等工具都需要在 不重启业务 JVM 的前提下与之交互。底层机制是 JDK 自带的 Attach API(com.sun.tools.attach,jdk.attach 模块):一个本地进程通过 PID 连上目标 HotSpot JVM,再在这条 attach 通道上发送不同种类的请求。 Attach 不是只有 loadAgent 一种用法。jcmd 的 Thread.print、JFR.start 等走 JVM 内置 Diagnostic Command,一般 不需要 再加载外部 agent JAR;BTrace 等才典型地 loadAgent。 本文说明 Attach 通道、公开 API、与 jcmd / BTrace 的关系。概念总图见 Java 领域知识关系图。容器、新版 JDK 注意点见文末。 是什么 Attach 让已启动的 HotSpot JVM 在运行中被另一进程「挂上」: 连接入口:VirtualMachine.attach(pid)(及 AttachProvider 发现 JVM) 通道上可发多种 attach 操作(见下节),不限于 loadAgent 其中一类操作会加载外部 Agent JAR,调用 agentmain(启动时 -javaagent 则走 premain) 不是远程 RPC:必须在本机(或共享进程命名空间,见文末),且一般要求与目标 JVM 相同的有效用户/组。 ...

Created 30306-05-30 · Updated 31316-05-31 · 3 min · 618 words · -