Unsafe类学习

2022年11月2日11:28:42

Unsafe

Unfase为我们提供了访问底层的机制,仅供java核心类库使用。

因此普通用户程序无法直接获取其实例,且unsafe的构造方法为私有的,但是我们可以通过反射获取。

1.获取unsafe

Unsafe有一个getUnsafe()方法可以获取实例:

@CallerSensitivepublicstatic UnsafegetUnsafe(){
        Classvar0= Reflection.getCallerClass();if(!VM.isSystemDomainLoader(var0.getClassLoader())){thrownewSecurityException("Unsafe");}else{return theUnsafe;}}

其返回的是thUnsafe,private static final Unsafe theUnsafe;,因此我们可以反射获取该实例:

publicstaticvoidmain(String[] args)throws NoSuchFieldException, IllegalAccessException{
        Unsafe unsafe=getUnsafe();
        System.out.println(unsafe);}/**
     * 获取Unsafe实例
     * @return
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */publicstatic UnsafegetUnsafe()throws NoSuchFieldException,IllegalAccessException{
        Field field= Unsafe.class.getDeclaredField("theUnsafe");
        field.setAccessible(true);return(Unsafe)field.get(null);}

2.unsafe创建对象

publicclassUnSafeDemo{publicstaticvoidmain(String[] args)throws NoSuchFieldException, IllegalAccessException, InstantiationException{//2.创建对象newInstance();}publicstaticvoidnewInstance()throws NoSuchFieldException, IllegalAccessException, InstantiationException{
        Unsafe unsafe=getUnsafe();
        Book book=(Book) unsafe.allocateInstance(Book.class);
        System.out.println(book.getName()+"\t"+book.getPrice());}}classBook{private String name;private Integer price;publicBook(){
        name="三国演义";
        price=77;}public StringgetName(){return name;}publicvoidsetName(String name){this.name= name;}public IntegergetPrice(){return price;}publicvoidsetPrice(Integer price){this.price= price;}}

打印结果为null null,因为:

allocateInstance方法用于创建一个类的实例,但是不会调用这个实例的构造方法,如果这个类还未被初始化,则初始化这个类。

3. 直接内存操作

// 分配内存(堆外)publicnativelongallocateMemory(long var1);// 重新分配内存publicnativelongreallocateMemory(long var1,long var3);// 内存初始化publicnativevoidsetMemory(long var1,long var3,byte var5);// 内存复制publicnativevoidcopyMemory(Object var1,long var2, Object var4,long var5,long var7);// 清除内存publicnativevoidfreeMemory(long var1);

我们可以调用allocateMemory方法为进程分配堆外的本地内存,但因为这部分内存不受JVM管辖范围,因此需要freeMemory方法进行回收

4. CAS操作

JUC中大量运用了CAS操作,CAS操作是juc包的基础。Unsafe中提供了int,long和CAS即Compare and Swap,是一种无锁化的算法,如果非要说是一种锁的化,那就是乐观锁,只要在操作数据的时候才会进行比较更新,比悲观锁处理效率更高。

参数1:要修改的对象

参数2: 偏移量

参数3:期望值oldValue

参数4: 更新的值newValue

publicfinalnativebooleancompareAndSwapObject(Object var1,long var2, Object var4, Object var5);publicfinalnativebooleancompareAndSwapInt(Object var1,long var2,int var4,int var5);publicfinalnativebooleancompareAndSwapLong(Object var1,long var2,long var4,long var6);

5. 异常抛出

使用Unsafe的throwException不需要再方法上抛出:

unsafe.throwException(newIllegalArgumentException());

6.线程相关

publicnativevoidunpark(Object var1);publicnativevoidpark(boolean var1,long var2);publicnativevoidmonitorEnter(Object var1);publicnativevoidmonitorExit(Object var1);publicnativebooleantryMonitorEnter(Object var1);

LockSupport中使用了park和unpark:

publicstaticvoidpark(Object blocker){
        Thread t= Thread.currentThread();setBlocker(t, blocker);
        UNSAFE.park(false,0L);setBlocker(t, null);}

线程需要阻塞时,调用park()方法,线程需要继续运行时,调用unpark()方法
monitorEnter:
锁定对象,必须通过monitorExit方法才能解锁。可重入的。
加了synchronized 关键字的代码段,生成的字节码文件会多出monitorentermonitorexit 两条指令

7. putXXX 和getXXX

以int为例:

  • getInt

    • 第一个参数:读取对象
    • 第二个参数:内存偏移地址
  • putInt

    • 第一个参数:修改对象
    • 第二个参数:内存偏移地址
    • 第三个参数:要修改的新值
publicnativeintgetInt(Object var1,long var2);publicnativevoidputInt(Object var1,long var2,int var4);
publicstaticvoidgetAndPut()throws InstantiationException, NoSuchFieldException{
        Unsafe unsafe=getUnsafe();
        Book book=newBook();
        Field field= book.getClass().getDeclaredField("name");
        unsafe.putObject(book,unsafe.objectFieldOffset(field),"新三国演义");
        System.out.println(book.getName());//新三国演义}

unsafe.objectFieldOffset(field): 获取对应字段的内存偏移地址

8. volatile相关

getXXXVolatile:以volatile的形式读取内存偏移地址为var2的对象的值。

putXXXVolatile:以volatile的形式修改内存偏移地址为var2的对象的值

既然使用了volatile,就说明该操作保证了有序性和可见性。

publicnative ObjectgetObjectVolatile(Object var1,long var2);publicnativevoidputObjectVolatile(Object var1,long var2, Object var4);

9.order相关

publicnativevoidputOrderedObject(Object var1,long var2, Object var4);publicnativevoidputOrderedInt(Object var1,long var2,int var4);publicnativevoidputOrderedLong(Object var1,long var2,long var4);

保证了有序性的写和修改。仅保证了有序性。因此不保证可见性和原子性。

  • 作者:一颗小陨石
  • 原文链接:https://blog.csdn.net/weixin_43696529/article/details/105060172
    更新时间:2022年11月2日11:28:42 ,共 3941 字。