Unsafe:查看版本 v3
由 mcst12345 于 2026-10-04 03:49 保存 · 2012 字节
'''Unsafe'''(<code>sun.misc.Unsafe</code>,位于 <code>jdk.unsupported</code> 模块)提供直接内存读写、字段偏移、CAS、不经构造器创建对象等底层操作,绕过 Java 的访问检查和类型安全。自Java9開始<code>sun.misc.Unsafe</code>為<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>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 内部布局,不同版本需要适配。
== 局限 ==
* 偏移量或地址写错可能会直接导致非法內存訪問。
* 对 record 和隐藏类的字段,<code>objectFieldOffset</code> 会抛异常。
* <code>defineClass</code> ,<code>defineAnonymousClass</code> 已於 JDK 11/17 移除並遷移至 <code>MethodHandles.Lookup</code>。
* JDK 23 起,<code>sun.misc.Unsafe</code> 的内存访问方法被标记为弃用待删除(JEP 471)。