通常 Java 代码都是运行在 JVM 中而不能直接访问系统硬件如进行内存分配释放等, 但如果有需要跳过 JVM 直接用 Java 访问系统硬件, 比如像 C 语言指针一样操作的话就可以调用 Unsafe 对象相关方法.
1,Unsafe 说明
Unsafe 类在 sun.misc 包下, 不属于 Java 标准. 但是很多 Java 基础类库, 包括一些高性能的开发库都是基于 Unsafe 类开发的, 比如 Netty,Hadoop,Kafka,JUC 并发包的基础 AQS 依赖的 CAS 操作和 LockSupport 类等. Unsafe 在提升 Java 运行效率, 增强 Java 底层操作能力方面起了很大的作用. 但它大部分操作都是绕过 JVM 通过 JNI 完成的, 因此它分配的内存需要手动 free, 过度的使用 Unsafe 类会让出错几率变大, 所以是非常危险的, Java 官方不建议直接使用.
2,Unsafe 类的使用
Unsafe 类是一个单例, 可通过 getUnsafe 方法获取, 但内部会检查限制, 只有是系统类加载器加载的类才能调用, 否则会抛出异常. 可通过 JVM 启动参数 - Xbootclasspath 指定要启动的类为启动类或通过反射获取到它的实例 [Unsafe 类中有一个私有的成员变量 theUnsafe, 我们可以用反射将其实例的访问属性设置为 true, 然后通过 File 的 get 方法获取] .
- Field f = Unsafe.class.getDeclaredField("theUnsafe");
- f.setAccessible(true);
- Unsafe unsafe = (Unsafe) f.get(null);
获取到 Unsafe 的实例之后, 我们就可以实现如下功能
内存管理: 内存的分配, 释放, 拷贝等, 利用 copyMemory 方法可以实现一个通用的对象浅拷贝方法.
非常规对象的实例化: 使用 allocateInstance 方法能直接生成实例对象, 无需调用构造方法和它的初始化方法, 在对象反序列化时会很有用, 能重建和设置 final 字段而不要调用构造方法.
操作类, 对象, 变量: 获取对象指针, 修改指针指向的数据.
数组操作: 使用 Unsafe 类的内存分配方法可以实现超大数组, 但注意要自己释放内存.
多线程同步: CAS 操作, 锁机制, LockSupport 的 pack,unpark 方法最终都是调用了 Unsafe 的 pack,unpack 方法.
内存屏障: 在 Java8 中新引入的, 用于定义内存屏障, 避免代码重排.
3,Java9 中 Unsafe 的变化
Unsafe 包路径发生变化, 被移动到 jdk.internal.misc 包下.
增加了非常详细的注释, 增加一个静态方法, 可以直接拿到 theUnsafe 对象.
说一说 Java 的 Unsafe 类 https://www.cnblogs.com/pkufork/p/java_unsafe.html
https://blog.csdn.net/luzheqi/article/details/79097682
来源: http://www.bubuko.com/infodetail-2629998.html