[TOC] Java的`Unsafe`类是一个非常底层且强大的工具,它提供了一系列可以直接操作内存地址的方法。这些方法绕过了Java语言的一些安全检查,因此使用它们可以实现一些高级特性,如直接内存访问、锁机制的实现等。然而,由于`Unsafe`提供了如此强大的功能,同时也带来了潜在的安全风险,因此Sun Microsystems(后来被Oracle收购)并未将其作为公共API正式发布,而是保持为内部使用的类。 ### 主要特点 - **非官方性**:`Unsafe`不是标准Java API的一部分,因此在不同的JVM实现中可能有所不同,甚至在不同版本的JDK中也可能发生变化。 - **性能**:由于绕过了Java的一些安全机制,使用`Unsafe`通常可以获得更好的性能。 - **灵活性**:可以用于实现更复杂的并发控制、内存管理等。 ### 常见方法 以下是`Unsafe`类中一些常用的方法: - **allocateMemory(long bytes)**: 分配指定字节数的内存。 - **freeMemory(long address)**: 释放之前分配的内存。 - **copyMemory(Object src, long srcOffset, Object dest, long destOffset, long bytes)**: 复制内存中的数据。 - **getInt(Object o, long offset)** 和 **putInt(Object o, long offset, int x)**: 获取或设置对象的特定偏移量处的int值。 - **objectFieldOffset(Field f)**: 获取给定字段的偏移量。 - **compareAndSwapInt(Object o, long offset, int expectedValue, int newValue)**: 实现原子性的比较并交换操作。 - **park(boolean isAbsolute, long time)** 和 **unpark(Thread thread)**: 控制线程的等待与唤醒,是实现自定义锁的基础。 ### 使用示例 下面是一个简单的例子,展示了如何使用`Unsafe`来获取一个字段的偏移量,并进行原子性的更新操作: ```java import sun.misc.Unsafe; import java.lang.reflect.Field; public class UnsafeExample { private static final Unsafe UNSAFE; private static final long VALUE_OFFSET; static { try { Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); UNSAFE = (Unsafe) field.get(null); Field valueField = UnsafeExample.class.getDeclaredField("value"); VALUE_OFFSET = UNSAFE.objectFieldOffset(valueField); } catch (NoSuchFieldException | IllegalAccessException e) { throw new ExceptionInInitializerError(e); } } private volatile int value; public void increment() { while (true) { int currentValue = value; int newValue = currentValue + 1; if (UNSAFE.compareAndSwapInt(this, VALUE_OFFSET, currentValue, newValue)) { break; } } } public static void main(String[] args) { UnsafeExample example = new UnsafeExample(); example.increment(); System.out.println(example.value); // 输出应该是1 } } ``` Java的`Unsafe`类虽然不是官方API的一部分,但它在许多核心库和并发工具中扮演了重要角色。特别是,在Java并发编程中,`Unsafe`被广泛用于实现高效的同步机制和高性能的数据结构。以下是一些使用了`Unsafe`的主要并发包和类: ### 1. `java.util.concurrent.atomic` 包 这个包中的类提供了原子变量的支持,利用`Unsafe`实现了高效的原子操作。主要类包括: - **`AtomicInteger`**: 提供了对整数的原子操作。 - **`AtomicLong`**: 提供了对长整数的原子操作。 - **`AtomicBoolean`**: 提供了对布尔值的原子操作。 - **`AtomicReference`**: 提供了对引用类型的原子操作。 - **`AtomicIntegerArray`**: 提供了对整数数组的原子操作。 - **`AtomicLongArray`**: 提供了对长整数数组的原子操作。 - **`AtomicReferenceArray`**: 提供了对引用类型数组的原子操作。 - **`AtomicMarkableReference`**: 提供了带有标记位的引用类型原子操作。 - **`AtomicStampedReference`**: 提供了带有版本号的引用类型原子操作。 这些类的核心方法(如`compareAndSet`、`getAndSet`等)都是通过调用`Unsafe`的相应方法实现的。 ### 2. `java.util.concurrent.locks` 包 这个包中的类提供了各种锁和同步工具,利用`Unsafe`实现了高效的锁机制。主要类包括: - **`ReentrantLock`**: 可重入的互斥锁。 - **`ReentrantReadWriteLock`**: 读写锁,允许多个读线程同时访问,但只允许一个写线程访问。 - **`Semaphore`**: 计数信号量,用于控制同时访问某个资源的线程数量。 - **`CountDownLatch`**: 同步辅助类,允许一个或多个线程等待其他线程完成操作。 - **`CyclicBarrier`**: 同步辅助类,允许一组线程彼此等待到达一个共同的屏障点。 这些类中的锁和同步机制通常依赖于`Unsafe`提供的原子操作和内存屏障。 ### 3. `java.util.concurrent` 包 这个包中的类提供了线程池、阻塞队列等并发工具,利用`Unsafe`实现了高效的线程管理和任务调度。主要类包括: - **`ThreadPoolExecutor`**: 线程池实现,用于管理和复用工作线程。 - **`BlockingQueue`**: 阻塞队列接口,提供了多种实现,如`LinkedBlockingQueue`、`ArrayBlockingQueue`等。 - **`ConcurrentHashMap`**: 线程安全的哈希表实现,使用分段锁和`Unsafe`提供的原子操作来保证线程安全。 - **`ConcurrentLinkedQueue`**: 线程安全的无界链表队列。 - **`ConcurrentSkipListMap`**: 线程安全的跳表实现。 ### 4. `java.util.concurrent.atomic` 包中的具体实现 以`AtomicInteger`为例,它的部分源码如下: ```java public class AtomicInteger extends Number implements java.io.Serializable { private static final long serialVersionUID = 6214790243416807050L; // setup to use Unsafe.compareAndSwapInt for updates private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long valueOffset; static { try { valueOffset = unsafe.objectFieldOffset (AtomicInteger.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } private volatile int value; public final int get() { return value; } public final void set(int newValue) { value = newValue; } public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); } // 其他方法... } ``` 除了在并发编程中广泛使用的`java.util.concurrent`包及其子包之外,`Unsafe`还在其他一些重要的Java API和框架中被使用。以下是一些常见的例子: ### 1. JVM 内部实现 - **HotSpot JVM**: HotSpot虚拟机内部使用`Unsafe`来实现一些底层操作,如对象创建、内存管理等。 ### 2. 反射和动态代理 - **`java.lang.reflect.Field`**: 在反射中,`Unsafe`用于直接访问对象的字段,绕过访问权限限制。 - **`java.lang.reflect.Method`**: 在方法调用中,`Unsafe`用于直接调用方法,提高性能。 ### 3. 序列化和反序列化 - **`java.io.ObjectInputStream` 和 `java.io.ObjectOutputStream`**: 在对象的序列化和反序列化过程中,`Unsafe`用于直接读写对象的内存。 ### 4. NIO (New I/O) - **`java.nio.Buffer`**: 在NIO中,`Unsafe`用于直接操作缓冲区的内存,提高I/O操作的性能。 - **`java.nio.DirectByteBuffer`**: 直接缓冲区使用`Unsafe`来分配和操作内存,避免了从堆内存到直接内存的拷贝。 ### 5. 并发数据结构 - **`java.util.concurrent.ConcurrentHashMap`**: 如前所述,`ConcurrentHashMap`使用`Unsafe`来实现高效的并发操作。 - **`java.util.concurrent.ConcurrentLinkedQueue`**: 使用`Unsafe`来实现无锁的队列操作。 - **`java.util.concurrent.ConcurrentSkipListMap`**: 使用`Unsafe`来实现高效的跳表操作。 ### 6. 并发工具类 - **`java.util.concurrent.CountDownLatch`**: 使用`Unsafe`来实现计数器的原子操作。 - **`java.util.concurrent.CyclicBarrier`**: 使用`Unsafe`来实现屏障的同步操作。 - **`java.util.concurrent.Semaphore`**: 使用`Unsafe`来实现信号量的原子操作。 - **`java.util.concurrent.Exchanger`**: 使用`Unsafe`来实现线程间的数据交换。 ### 7. 并发锁 - **`java.util.concurrent.locks.ReentrantLock`**: 使用`Unsafe`来实现可重入锁的原子操作。 - **`java.util.concurrent.locks.ReentrantReadWriteLock`**: 使用`Unsafe`来实现读写锁的原子操作。 ### 8. 并发原子类 - **`java.util.concurrent.atomic.AtomicInteger`**: 使用`Unsafe`来实现整数的原子操作。 - **`java.util.concurrent.atomic.AtomicLong`**: 使用`Unsafe`来实现长整数的原子操作。 - **`java.util.concurrent.atomic.AtomicBoolean`**: 使用`Unsafe`来实现布尔值的原子操作。 - **`java.util.concurrent.atomic.AtomicReference`**: 使用`Unsafe`来实现引用类型的原子操作。 - **`java.util.concurrent.atomic.AtomicIntegerArray`**: 使用`Unsafe`来实现整数数组的原子操作。 - **`java.util.concurrent.atomic.AtomicLongArray`**: 使用`Unsafe`来实现长整数数组的原子操作。 - **`java.util.concurrent.atomic.AtomicReferenceArray`**: 使用`Unsafe`来实现引用类型数组的原子操作。 - **`java.util.concurrent.atomic.AtomicMarkableReference`**: 使用`Unsafe`来实现带有标记位的引用类型的原子操作。 - **`java.util.concurrent.atomic.AtomicStampedReference`**: 使用`Unsafe`来实现带有版本号的引用类型的原子操作。 ### 9. 其他框架和库 - **Guava**: Google Guava库中的一些并发工具类也使用了`Unsafe`来实现高效的并发操作。 - **Netty**: 高性能网络通信框架Netty中使用`Unsafe`来优化内存管理和I/O操作。 - **Hadoop**: Hadoop框架中的一些组件也使用了`Unsafe`来提高性能。 ### 示例代码 以下是一个简单的示例,展示了如何使用`Unsafe`来实现一个简单的原子整数类: ```java import sun.misc.Unsafe; import java.lang.reflect.Field; public class SimpleAtomicInteger { private static final Unsafe UNSAFE; private static final long VALUE_OFFSET; static { try { Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); UNSAFE = (Unsafe) field.get(null); Field valueField = SimpleAtomicInteger.class.getDeclaredField("value"); VALUE_OFFSET = UNSAFE.objectFieldOffset(valueField); } catch (NoSuchFieldException | IllegalAccessException e) { throw new ExceptionInInitializerError(e); } } private volatile int value; public int get() { return value; } public void set(int newValue) { value = newValue; } public boolean compareAndSet(int expect, int update) { return UNSAFE.compareAndSwapInt(this, VALUE_OFFSET, expect, update); } public static void main(String[] args) { SimpleAtomicInteger atomicInt = new SimpleAtomicInteger(); atomicInt.set(10); boolean result = atomicInt.compareAndSet(10, 20); System.out.println(result); // 输出 true System.out.println(atomicInt.get()); // 输出 20 } } ``` ### 总结 `Unsafe`类通过提供底层的内存操作和原子操作,使得Java并发工具能够高效地实现同步和并发控制。虽然`Unsafe`不是官方推荐的API,但在Java并发编程中发挥了重要作用。使用这些并发工具时,开发者通常不需要直接接触`Unsafe`,因为这些工具已经封装好了底层的复杂操作。