Mmc秒杀圈百科 

Unsafe:查看版本 v2

由 朝武芳乃 于 2026-10-04 02:03 保存 · 2242 字节
''本条基于 Java 17(Minecraft 1.20.1 所用版本)。'' '''Unsafe'''(<code>sun.misc.Unsafe</code>,位于 <code>jdk.unsupported</code> 模块)提供直接内存读写、字段偏移、CAS、不经构造器创建对象等底层操作,绕过 Java 的访问检查和类型安全。JDK 内部另有一个功能更全的 <code>jdk.internal.misc.Unsafe</code>,默认不对外导出。 == 获取 == 构造器私有,通常用 [[Reflection]] 读取静态字段 <code>theUnsafe</code>: <code>Field f = Unsafe.class.getDeclaredField("theUnsafe"); f.setAccessible(true); Unsafe u = (Unsafe) f.get(null);</code> 由于 <code>jdk.unsupported</code> 开放了 <code>sun.misc</code> 包,这个写法在 Java 17 中依然可用。 == 常用能力 == * <code>objectFieldOffset</code> / <code>staticFieldBase</code> / <code>staticFieldOffset</code> 配合 <code>getObject</code>、<code>putObject</code>、<code>getInt</code>、<code>putInt</code> 等:直接读写任意字段,包括 <code>final</code> 字段。 * <code>allocateInstance</code>:不调用构造器创建对象。 * <code>compareAndSwap*</code> / <code>getAndSet*</code>:原子操作。 * <code>allocateMemory</code> / <code>freeMemory</code> / <code>getAddress</code> / <code>putAddress</code>:堆外内存。 * 读写对象头:[[klassptr]] 就是用 <code>getInt</code> / <code>putInt</code> 改写对象头里的类型指针,从而改变对象在 JVM 眼中的类型。 * 读取 <code>MethodHandles.Lookup.IMPL_LOOKUP</code> 等 JDK 内部静态字段,见 [[MethodHandle]]。 * 修改 Klass 内部标志:例如清除[[隐藏类]]的 hidden 标志,使它被当作普通类,从而能被 [[retransformClasses]] / [[redefineClasses]] 处理;依赖 JDK 内部布局,不同版本需要适配。 == 局限 == * 偏移量或地址写错会直接导致 JVM 崩溃,而不是抛异常。 * 对 record 和隐藏类的字段,<code>objectFieldOffset</code> 会抛异常。 * <code>defineClass</code> 已在 JDK 11 移除,<code>defineAnonymousClass</code> 已在 JDK 17 移除,需改用 <code>MethodHandles.Lookup</code> 的对应方法。 * JDK 23 起,<code>sun.misc.Unsafe</code> 的内存访问方法被标记为弃用待删除(JEP 471)。

其他版本