Unsafe

概述 

  Unsafe 类是Java平台的一部分,位于 sun.misc 包中。

  这是一个非公开的类,意味着它不是为外部使用设计的,并且可能在未来的版本中更改或移除。

  尽管如此,Unsafe 类提供了对底层硬件和内存模型的直接访问能力,这对于实现高性能的系统级编程非常有用。

特点  

  1. 直接内存访问Unsafe 类允许直接读写内存地址,这对于实现高效的数据结构(如直接缓冲区)非常有用。
  2. 底层操作:提供了对CPU特定指令的支持,如原子操作(CAS操作)。
  3. 反射增强:提供了反射相关的功能,可以访问私有成员或执行私有的构造函数。
  4. 类型转换:允许执行某些类型的转换,这些转换在标准的Java类型系统中是不允许的。

主要方法

直接内存操作  

  • allocateMemory(long bytes):分配指定大小的直接内存。
  • freeMemory(long address):释放之前分配的直接内存。
  • putObject(Object base, long offset, Object value):在指定偏移量处存储对象引用。
  • getObject(Object base, long offset):从指定偏移量处读取对象引用。

示例

       Unsafe unsafe = getUnsafe();

        // 例如,直接内存操作
        long address = unsafe.allocateMemory(8); // 分配8字节的内存
        unsafe.putLong(address, 1L); // 在分配的内存中存储一个长整型值
        System.out.println(unsafe.getLong(address)); // 输出:1
        unsafe.freeMemory(address); // 释放内存

 

反射相关操作

  用于增强反射功能

  通过 Unsafe 类,我们可以执行一些常规反射API无法做到的事情,例如访问私有字段、方法和构造函数

 

  • staticFieldBase(Field field):获取字段所在的对象。
  • staticFieldOffset(Field field):获取静态字段的偏移量。
  • objectFieldOffset(Field field):获取对象字段的偏移量。  

注意事项

  • 安全性:使用 Unsafe 类增强反射功能虽然可以访问私有成员,但这可能破坏封装性和安全性。在实际应用中,应尽量避免使用这种方式访问私有成员
  • 兼容性Unsafe 类不是公开的API,其行为可能在未来的JVM版本中发生改变。如果依赖于 Unsafe 类,你的代码可能需要随着JVM的变化而更新
  • 调试和维护:直接使用 Unsafe 类进行反射操作会使代码难以理解和维护,并且可能引入难以发现的错误。

 

替代方案

  对于大多数情况,使用标准的反射API已经足够满足需求,并且更加安全可靠

  如果确实需要访问私有成员,可以考虑重构代码来暴露必要的公共API,而不是直接使用 Unsafe 类。

  此外,还可以使用代理模式或其他设计模式来实现类似的功能。

 

示例

public class UnsafeReflectionExample {
    private static final Unsafe UNSAFE;

    static {
        try {
            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafeInstance.setAccessible(true);
            UNSAFE = (Unsafe) theUnsafeInstance.get(null);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new Error("Could not initialize intrinsics", e);
        }
    }

    public static void main(String[] args) {
        // 创建一个测试对象
        TestClass testObj = new TestClass();

        // 使用Unsafe访问私有字段
        accessPrivateField(testObj);
    }

    private static void accessPrivateField(TestClass testObj) {
        try {
            Field privateField = TestClass.class.getDeclaredField("privateField");
            long offset = UNSAFE.objectFieldOffset(privateField);
            UNSAFE.putInt(testObj, offset, 42); // 设置私有字段的值
            System.out.println("Private field value: " + UNSAFE.getInt(testObj, offset)); // 输出:Private field value: 42
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

    // 测试类
    public static class TestClass {
        private int privateField;

        private TestClass() {
            // 私有构造函数
        }

        private void doSomething() {
            // 私有方法
            System.out.println("Doing something...");
        }
    }
}

   

CAS原子操作

  用于实现高效的并发控制

  原子操作是指在多线程环境下能够保证操作的完整性和一致性的一组操作。

  Unsafe 类中的原子操作主要是基于(Compare and Swap,CAS)机制

  利用了硬件级别的 CAS 指令来实现原子更新;  

 

public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);

    public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

    public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

  对象引用、字段偏移量、期望的旧值和新值

示例

  使用并发工具类:AtomicInteger...

 

posted on 2023-10-24 10:15  anpeiyong  阅读(4)  评论(0编辑  收藏  举报

导航