C语言变量unsafe,Java中Unsafe使用详解

本文详细介绍了Java中的Unsafe类,包括其在内存操作、并发原子类、线程控制等方面的应用。Unsafe提供了直接访问内存、CAS操作、线程 unpark 和 park 方法,以及类和对象操作等功能。尽管Unsafe能提升性能,但也存在安全隐患,使用时需谨慎。此外,文章还展示了如何获取和使用Unsafe实例,以及其在原子操作类实现中的关键作用。
摘要由CSDN通过智能技术生成

45f3dfd4e04cbbc000cd9784971d77b2.png

Unsafe介绍

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

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

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

内存相关

b7c9cb165b19f82bbfe613a5bb4a3834.png

CAS相关

8738990261dd3329889e043dfb5eb925.png

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

privatestaticfinal Unsafe unsafe = Unsafe.getUnsafe();

private staticfinal long valueOffset;

static{

try {

valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));

} catch (Exception ex) { throw new Error(ex); }

}

publicfinalintgetAndSet(intnewValue) {

returnunsafe.getAndSetInt(this, valueOffset, newValue);

}

线程相关

1d111f008aaa2328623047abae209438.png

LockSupport类中有应用unpark,park

publicstaticvoid park(Object blocker) {

Thread t = Thread.currentThread();

setBlocker(t, blocker);

UNSAFE.park(false, 0L);

setBlocker(t, null);

}

publicstaticvoid unpark(Thread thread) {

if (thread != null)

UNSAFE.unpark(thread);

}

Class相关

4f5f5640ad6157e59e1a1c1510bd6202.png

对象操作相关

864e81cb0b12b4624e50724a9a376401.png

系统相关

567d271d31cb43dde6a403d370b5bfa6.png

内存屏障

aee63426f0357d85694a2754be818c3d.png

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

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

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

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

privatestaticfinal sun.misc.Unsafe U;

static{

try {

U = sun.misc.Unsafe.getUnsafe();

} catch (Exception e) {

throw new Error(e);

}

}

publicboolean validate(long stamp) {

U.loadFence();

return(stamp & SBITS) == (state & SBITS);

}

U.loadFence();

Unsafe.java

publicfinal class Unsafe {

private staticnative void registerNatives();

static{

registerNatives();

sun.reflect.Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe");

}

private Unsafe() {}

private staticfinal Unsafe theUnsafe = new Unsafe();

// ...

}

获取Unsafe实例

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

方法1

Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe") ;

theUnsafe.setAccessible(true) ;

Unsafe unsafe = (Unsafe) theUnsafe.get(null) ;

方法2

privatestaticUnsafe unsafe =null;

static{

try {

Constructor cons = Unsafe.class.getDeclaredConstructor() ;

cons.setAccessible(true) ;

unsafe = cons.newInstance() ;

} catch (Exception e) {

e.printStackTrace();

}

}

Unsafe简单应用

inti = 0 ;

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

}

Unsafe对象操作

privatestaticUnsafe unsafe =null;

static{

try {

Constructor cons = Unsafe.class.getDeclaredConstructor() ;

cons.setAccessible(true) ;

unsafe = cons.newInstance() ;

} catch (Exception e) {

e.printStackTrace();

}

}

publicstaticvoid 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();

}

}

执行结果:

3dd631edbce253596541b82f3ff11a6a.png

对象操作2:

private Person p = new Person("1","张三") ;

publicstaticvoid 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()) ;

}

516cbfccf0e83652e6bfa9a709350c2c.png

Unsafe创建对象

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

Constructor cons = (Constructor) ReflectionFactory.getReflectionFactory().newConstructorForSerialization(Teacher.class,

Object.class.getConstructor());

cons.setAccessible(true);

Teacher t = cons.newInstance() ;

System.out.println(t) ;

Unsafe简单实现原子操作类

publicclass AtomicCount {

private staticUnsafe unsafe ;

private intvalue ;

private staticlong 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();

}

}

publicAtomicCount(intvalue) {

this.value = value ;

}

publicfinalintget() {

returnvalue;

}

publicfinalintgetAndIncrement() {

returnunsafe.getAndAddInt(this, valueOffset, 1);

}

}

完毕!!!

【编辑推荐】

【责任编辑:姜华 TEL:(010)68476606】

点赞 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值