關於通過Unsafe.getUnsafe()方法拿Unsafe對象拋出SecurityException異常的原因


眾所周知,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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM