关于通过Unsafe.getUnsafe()方法拿Unsafe对象抛出SecurityException异常的原因

摘要:
=null){ClassLoader.checkClassLoaderPermission(cl,Reflection.getCallerClass());}returncl;}ClassLoader。checkClassLoaderPermission()源代码staticvoidcheckClassLoaderPermission(ClassLoadercl,Class˂?
众所周知,Java中的Unsafe对象可以直接调用内存,而且CAS等原子性操作中,也都是使用Unsafe对象,但当我们自己准备去使用Unsafe.getUnsafe()函数获取Unsafe对象时,却会抛出SecurityException:Unsafe异常,原因是因为双亲委派制的保护机制
我们看一下Unsafe.getUnsafe()函数的源码:
@CallerSensitive
public static Unsafe getUnsafe() {
    // ----- 这里去获取当前类的ClassLoader加载器
    Class var0 = Reflection.getCallerClass();
    // ----- 判断var0是不是BootstrapClassLoader
    if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
        // ----- 否:抛出SecurityException异常
        throw new SecurityException("Unsafe");
    } else {
        // ----- 是:返回unsafe对象
        return theUnsafe;
    }
}
Class.getClassLoader()源码
@CallerSensitive
public ClassLoader getClassLoader() {
    ClassLoader cl = getClassLoader0();
    if (cl == null)
        return null;
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass());
    }
    return cl;
}
ClassLoader.checkClassLoaderPermission()源码
static void checkClassLoaderPermission(ClassLoader cl, Class<?> caller) {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        // caller can be null if the VM is requesting it
        ClassLoader ccl = getClassLoader(caller);
        if (needsClassLoaderPermissionCheck(ccl, cl)) {
            sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
        }
    }
}
VM.isSystemDomainLoader()源码
public static boolean isSystemDomainLoader(ClassLoader var0) {
    // ----- 重点是在这里:
    // --- 当结果为true时:说明var0是Bootstrap类加载器,
    // -- 当结果为false时:说明var0是Extension || App || Custom 等类加载器
    // ----- 所以回到getUnsafe()函数,当这个函数返回false时,会直接抛异常,不允许加载Unsafe
    return var0 == null;
}

免责声明:文章转载自《关于通过Unsafe.getUnsafe()方法拿Unsafe对象抛出SecurityException异常的原因》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇(入门篇)Python web框架FastAPI——一个比Flask和Tornada更高性能的API 框架查找nginx安装的路径下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

不知道怎么提高代码可扩展性?来看看优秀框架源码中的这几种设计模式吧!

为什么要提高代码扩展性 我们写的代码都是为了一定的需求服务的,但是这些需求并不是一成不变的,当需求变更了,如果我们代码的扩展性很好,我们可能只需要简单的添加或者删除模块就行了,如果扩展性不好,可能所有代码都需要重写,那就是一场灾难了,所以提高代码的扩展性是势在必行的。怎样才算有好的扩展性呢?好的扩展性应该具备以下特征: 需求变更时,代码不需要重写。 局部...

Linux进程调度与源码分析(三)——do_fork()的实现原理

        用户层的fork(),vfork(),clone()API函数在执行时,会触发系统调用完成从用户态陷入到内核态的过程,而上述函数的系统调用,最终实现都是通过内核函数do_fork()完成,本篇着重分析do_forkI()函数的实现过程。         Linux操作系统中,产生一个新的进程和产生一个新的线程对于内核来说,最为本质的区别在于...

netty源码-server端绑定端口流程

仅用于记录在分析netty源码的日志 源码调用关系图 Netty Server示例 EventLoopGroup boss = new NioEventLoopGroup(1); EventLoopGroup io = new NioEventLoopGroup(); ServerBootstrap boo...

BufferedReader源码分析

BufferedReader源码分析1、案例代码 假设b.txt存储了abcdegfhijk public static void main(String[] args) throws IOException {//字符缓冲流BufferedReader bufferedReader=new BufferedReader(new FileReader(ne...

经典的CSS代码(转)

Web开发技术每年都在革新,浏览器已逐渐支持CSS3特性,并且网站设计师和前端开发者普遍采用这种新技术进行设计与开发。但仍然有一些开发者迷恋着一些CSS2代码。 分享20段非常专业的CSS2/CSS3代码供大家使用,你可以把它们保存在IDE里、或者存储在CSS文档里,这些代码片段绝对会给你带来意外的惊喜。 1. CSS Resets 网络上关于CSS重置的...

《老罗Android开发视频教程》老罗来交国庆的答卷了

     之前在博客园、开源中国、安卓巴士发表的《老罗将死,或者Android也将就换代,但是互联网的,共享,互助精神将永存》,计划出300集免费的、高质量的、全面的Android开发视频教程,得到了很多人的支持,但是同样也遭到了一些人的质疑,说老罗是空有一翻热情,肯定会半途而废的,因此老罗决定在隔一段时间就在博客园里面给大家交个答卷,也让这些人看...