Unsafe:查看版本 v1
由 朝武芳乃 于 2026-10-04 01:15 保存 · 2019 字节
''本条基于 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]]。
== 局限 ==
* 偏移量或地址写错会直接导致 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)。