本条基于 Java 17(Minecraft 1.20.1 所用版本)。
InstrumentationImpl(sun.instrument.InstrumentationImpl,位于 java.instrument 模块)是 Instrumentation 接口在 JDK 中的内部实现。
结构
- 保存一个指向本地 JPLIS agent 的指针(
long类型字段),retransformClasses、redefineClasses等操作通过 native 方法交给 JVMTI 完成。 - 内部用两个
TransformerManager分别管理普通的和可重转换的ClassFileTransformer。 - 类加载或重转换时,JVM 回调它的
transform方法,再依次调用已注册的转换器。
与 Agent 加载的关系
JVM 加载 JavaAgent 时,由本地代码创建它的实例,再通过 loadClassAndCallPremain / loadClassAndCallAgentmain 调用 agent 的 premain / agentmain,把自己作为参数传进去。
非常规获取
sun.instrument包不对外导出,直接访问需要--add-exports/--add-opens,或借助 MethodHandle 的IMPL_LOOKUP、Unsafe 绕过。- 有人在不使用
-javaagent的情况下,自行拿到 JPLIS agent 指针后调用它的私有构造器来构造实例。这种做法依赖 JDK 内部实现,构造器参数在不同版本间可能变化。