Mmc秒杀圈百科 

Unsafe

由 朝武芳乃管理员 最后编辑于 2026-10-04 02:03 · 当前版本 v2
标签:技术正经内容
你尚未登录。登录后可编辑本页与创建新条目 —— 登录 或 注册账号。

本条基于 Java 17(Minecraft 1.20.1 所用版本)。

Unsafe(sun.misc.Unsafe,位于 jdk.unsupported 模块)提供直接内存读写、字段偏移、CAS、不经构造器创建对象等底层操作,绕过 Java 的访问检查和类型安全。JDK 内部另有一个功能更全的 jdk.internal.misc.Unsafe,默认不对外导出。

获取

构造器私有,通常用 Reflection 读取静态字段 theUnsafe:
Field f = Unsafe.class.getDeclaredField("theUnsafe"); f.setAccessible(true); Unsafe u = (Unsafe) f.get(null);
由于 jdk.unsupported 开放了 sun.misc 包,这个写法在 Java 17 中依然可用。

常用能力

  • objectFieldOffset / staticFieldBase / staticFieldOffset 配合 getObject、putObject、getInt、putInt 等:直接读写任意字段,包括 final 字段。
  • allocateInstance:不调用构造器创建对象。
  • compareAndSwap* / getAndSet*:原子操作。
  • allocateMemory / freeMemory / getAddress / putAddress:堆外内存。
  • 读写对象头:klassptr 就是用 getInt / putInt 改写对象头里的类型指针,从而改变对象在 JVM 眼中的类型。
  • 读取 MethodHandles.Lookup.IMPL_LOOKUP 等 JDK 内部静态字段,见 MethodHandle。
  • 修改 Klass 内部标志:例如清除隐藏类的 hidden 标志,使它被当作普通类,从而能被 retransformClasses / redefineClasses 处理;依赖 JDK 内部布局,不同版本需要适配。

局限

  • 偏移量或地址写错会直接导致 JVM 崩溃,而不是抛异常。
  • 对 record 和隐藏类的字段,objectFieldOffset 会抛异常。
  • defineClass 已在 JDK 11 移除,defineAnonymousClass 已在 JDK 17 移除,需改用 MethodHandles.Lookup 的对应方法。
  • JDK 23 起,sun.misc.Unsafe 的内存访问方法被标记为弃用待删除(JEP 471)。
你对本条的回应 · 登录后可表态

讨论(0)

讨论不进入条目正文的版本历史,适合提出修改建议、指出问题或补充来源。
还没有人讨论这个条目。你可以提出修改建议、指出问题或补充来源。

发表话题

请先 登录 后再参与讨论。