Java中Unsafe使用详解

开发 后端
在程序中过度、不正确使用Unsafe类会使得程序出错的概率变大,使得Java这种安全的语言变得不再“安全”,因此对Unsafe的使用一定要慎重。

[[392756]]

Unsafe介绍

Unsafe是位于sun.misc包下的一个类,主要提供一些用于执行低级别、不安全操作的方法,如直接访问系统内存资源、自主管理内存资源等,这些方法在提升Java运行效率、增强Java语言底层资源操作能力方面起到了很大的作用。但由于Unsafe类使得Java语言拥有了类似C语言指针一样操作内存空间的能力,这无疑也增加了程序发生相关指针问题的风险。在程序中过度、不正确使用Unsafe类会使得程序出错的概率变大,使得Java这种安全的语言变得不再“安全”,因此对Unsafe的使用一定要慎重。

java.util.concurrent.atomic包下的原子操作类,基本都是使用Unsafe实现的。

Unsafe提供的API大致可分为内存操作、CAS、Class、对象操作、线程、系统信息获取、内存屏障、数组操作等几类。

内存相关

CAS相关

java.util.concurrent.atomic包中的原子类基本都用的Unsafe

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); } 

public final int getAndSet(int newValue) { 
  return unsafe.getAndSetInt(this, valueOffset, newValue); 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

线程相关

LockSupport类中有应用unpark,park

public static void park(Object blocker) { 
  Thread t = Thread.currentThread(); 
  setBlocker(t, blocker); 
  UNSAFE.park(false, 0L); 
  setBlocker(t, null); 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
public static void unpark(Thread thread) { 
  if (thread != null
    UNSAFE.unpark(thread); 

  • 1.
  • 2.
  • 3.
  • 4.

Class相关

对象操作相关

系统相关

内存屏障

loadFence:保证在这个屏障之前的所有读操作都已经完成。

storeFence:保证在这个屏障之前的所有写操作都已经完成。

fullFence:保证在这个屏障之前的所有读写操作都已经完成。

在java8中 有这个StampedLock类,该类中应用了内存屏障功能。

private static final sun.misc.Unsafe U; 
static { 
  try { 
    U = sun.misc.Unsafe.getUnsafe(); 
  } catch (Exception e) { 
    throw new Error(e); 
  } 

public boolean validate(long stamp) { 
  U.loadFence(); 
  return (stamp & SBITS) == (state & SBITS); 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

 

U.loadFence(); 
  • 1.

 

Unsafe.java

public final class Unsafe { 
 
    private static native void registerNatives(); 
    static { 
        registerNatives(); 
        sun.reflect.Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe"); 
    } 
 
    private Unsafe() {} 
 
    private static final Unsafe theUnsafe = new Unsafe(); 
    // ... 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

获取Unsafe实例

Unsafe类是final且是单例的,并且theUnsafe字段是private;通过如下方法获取实例

方法1

Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe") ; 
theUnsafe.setAccessible(true) ; 
Unsafe unsafe = (Unsafe) theUnsafe.get(null) ; 
  • 1.
  • 2.
  • 3.

方法2

private static Unsafe unsafe = null ; 
     
static { 
    try { 
        Constructor<Unsafe> cons = Unsafe.class.getDeclaredConstructor() ; 
        cons.setAccessible(true) ; 
        unsafe = cons.newInstance() ; 
    } catch (Exception e) { 
        e.printStackTrace(); 
    } 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

Unsafe简单应用

int i = 0 ; 
     
public static void main(String[] args) throws Exception { 
    UnsafeDemo d = new UnsafeDemo() ; 
    // 获取Unsafe实例 
    Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe") ; 
    theUnsafe.setAccessible(true) ; 
    Unsafe unsafe = (Unsafe) theUnsafe.get(null) ; 
    // 获取类的实例变量 
    Field f = UnsafeDemo.class.getDeclaredField("i") ; 
    // 获取字段相对Java对象的"起始地址"的偏移量 
    long fieldOffset = unsafe.objectFieldOffset(f) ; 
    System.out.println(fieldOffset) ; 
    // 设置值 
    boolean success = unsafe.compareAndSwapInt(d, fieldOffset, 0, 10) ; 
    System.out.println(success) ; 
    System.out.println(d.i) ; 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

Unsafe对象操作

private static Unsafe unsafe = null ; 
     
static { 
try { 
        Constructor<Unsafe> cons = Unsafe.class.getDeclaredConstructor() ; 
        cons.setAccessible(true) ; 
        unsafe = cons.newInstance() ; 
    } catch (Exception e) { 
        e.printStackTrace(); 
    } 

public static void allocate() { 
    try { 
        Person p = (Person)unsafe.allocateInstance(Person.class) ; 
        p.setId("s001"); 
        System.out.println(p.getValue()) ; 
        System.out.println(p.getId()) ; 
    } catch (Exception e) { 
        e.printStackTrace(); 
    } 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.

执行结果:

对象操作2:

private Person p = new Person("1""张三") ; 
     
public static void main(String[] args) throws Exception { 
  UnSafeObjectDemo d = new UnSafeObjectDemo() ; 
  Field field = Unsafe.class.getDeclaredField("theUnsafe") ; 
    field.setAccessible(true) ; 
    Unsafe unsafe = (Unsafe) field.get(null) ; 
    Field f = d.getClass().getDeclaredField("p") ; 
    long offset = unsafe.objectFieldOffset(f) ; 
    System.out.println(offset) ; 
    boolean res = unsafe.compareAndSwapObject(d, offset, d.p, new Person("2""李四")) ; 
    System.out.println(res) ; 
    System.out.println(d.p.getName()) ; 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

Unsafe创建对象

当不知道即将使用的对象有何构造函数,或是不想使用现有对象的构造函数创建对象时,可以通过如下方式:

Constructor<Teacher> cons = (Constructor<Teacher>) ReflectionFactory.getReflectionFactory().newConstructorForSerialization(Teacher.class, 
                Object.class.getConstructor()); 
cons.setAccessible(true); 
Teacher t = cons.newInstance() ; 
System.out.println(t) ; 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

Unsafe简单实现原子操作类

public class AtomicCount { 
     
    private static Unsafe unsafe ; 
     
    private int value ; 
    private static long valueOffset ; 
     
    static { 
        try { 
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe") ; 
            theUnsafe.setAccessible(true) ; 
            unsafe = (Unsafe) theUnsafe.get(null) ; 
             
            Field f = AtomicCount.class.getDeclaredField("value") ; 
            valueOffset = unsafe.objectFieldOffset(f) ; 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
    } 
     
    public AtomicCount(int value) { 
        this.value = value ; 
    } 
     
    public final int get() { 
        return value; 
    } 
     
    public final int getAndIncrement() { 
        return unsafe.getAndAddInt(this, valueOffset, 1); 
    } 
     

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.

完毕!!!

 

责任编辑:姜华 来源: 今日头条
相关推荐

2021-04-29 07:43:51

JavaUnsafe 基础native方法

2022-06-07 08:31:44

JavaUnsafe

2016-09-18 16:58:09

JavaProperties

2021-06-03 08:35:25

Go团队Unsafe.Poin

2021-10-12 23:10:58

UnsafeJavaJDK

2024-09-19 20:59:49

2015-09-09 08:45:49

JavaThreadLocal

2011-08-15 14:27:51

CocoaRunLoop

2011-03-28 09:35:06

iBaitsSqlMapClien

2009-07-20 14:24:13

Math.pow()方Java ME

2021-10-19 21:39:51

Unsafe构造器内存

2023-10-05 11:12:06

JUCUnsafe安全

2010-07-22 15:22:58

BlackBerry开

2010-10-09 10:30:03

JS event

2010-09-08 17:15:45

SQL循环结构

2020-12-04 10:11:26

Unsafejava并发包

2012-02-09 10:18:55

Java

2011-09-27 10:23:24

Java反射机制

2023-04-23 08:49:17

Java接口Future

2025-01-15 07:00:00

Java代码Lambda
点赞
收藏

51CTO技术栈公众号