本条基于 Java 17(Minecraft 1.20.1 所用版本)。
MethodHandle(java.lang.invoke.MethodHandle)是 Java 7 引入的方法句柄,可以指向方法、构造器或字段的 getter / setter,通过 invokeExact / invoke 调用。
获取
通过 MethodHandles.Lookup:findVirtual、findStatic、findSpecial、findConstructor、findGetter / findSetter、findStaticGetter / findStaticSetter,或用 unreflect* 把 Reflection 得到的对象转成句柄。
访问权限
- Lookup 的权限取决于创建它的类:
MethodHandles.lookup()只有调用者的权限;privateLookupIn要求目标模块对调用者开放。 MethodHandles.Lookup.IMPL_LOOKUP是 JDK 内部拥有全部权限(TRUSTED)的私有静态字段。常见做法是用 Unsafe 的staticFieldBase/staticFieldOffset+getObject读出它,从而无视模块封装访问任意成员,也能为final字段生成 setter。- 被 JIT 常量折叠的
static final字段,即使改了值,已编译的代码也可能仍用旧值。
与反射的对比
- 访问检查在创建句柄时做一次,调用时不再检查。
- 存在
static final字段里的句柄可被 JIT 内联,性能接近直接调用。 - 字段的原子操作可用同包下的
VarHandle(Java 9+)。
在模组中
可用它高效地读写 ServerLevel、EntityLookup 等类的私有字段;与反射一样,生产环境要使用 SRG 名。