【Java基础】反射-UnSafe

7 篇文章 0 订阅

如何正确创建UnSafe实例

Long offset = Unsafe.getUnsafe().objectFieldOffset(nameField);
unsafe.compareAndSwapObject(targetInstance,offset,name,"hello unsafe");

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6WcFdrp5-1628667545948)(/Users/tim/Desktop/截屏2021-08-11 上午10.27.16.png)]

查看getUnsafe方法,会判断当前类的class loader是否为null,但当前类的加载器是AppClassLoader实例,所以这里判断为真,抛出上面的异常。所以只能用BootstrapClassLoader加载器中调用的类使用这个unsage,比如concurrenthashmap是在BootstrapClassLoader中加载的,getClassLoader0()获取出来是为null的,所以不会抛出异常。

@CallerSensitive
public static Unsafe getUnsafe() {
    Class var0 = Reflection.getCallerClass();
    if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
        throw new SecurityException("Unsafe");
    } else {
        return theUnsafe;
    }
}
public static boolean isSystemDomainLoader(ClassLoader var0) {
    return var0 == null;
}

那如何得到UnSafe的实例呢?因为Unsafe中有个theUnsafe的属性,该属性在static静态代码块中被实例化类,所以可以通过放射来获取这个已经实例化的对象属性,从而获得unsafe对象:

static {
    registerNatives();
    Reflection.registerMethodsToFilter(Unsafe.class, new String[]{"getUnsafe"});
    theUnsafe = new Unsafe();
    ...
    }

如何使用UnSafe进行反射?

创建一个反射的目标类用于后面的例子

public class Hello {

    private String name;

    public void hello(String name){
        System.out.println("hello "+name);
    }

    public void say(String name){
        System.out.println("say "+name);
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

}

通过UnSafe操作目标对象的属性

//通过反射拿到Unsafe类的成员theUnsafe,该成员已经在UnSafe类的静态代码块中被实例化了
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unsafe = (Unsafe) theUnsafe.get(null);

Class clazz = Hello.class;
Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true);

Hello targetInstance = new Hello();
//这里可以使用反射拿到成员变量theUnsafe
Long offset = unsafe.objectFieldOffset(nameField);
unsafe.compareAndSwapObject(targetInstance,offset,name,"hello unsafe");
String name = (String) unsafe.getObject(targetInstance,offset);
System.out.println("name: "+name);

结语

当然UnSafe还有内存操作、内存屏障、线程调度等功能,后续会有专题文章。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值