前言
在閱讀Unsafe源碼是,以下是Unsafe部分源碼:
@CallerSensitive
public static Unsafe getUnsafe() {
Class var0 = Reflection.getCallerClass();
if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
throw new SecurityException("Unsafe");
} else {
return theUnsafe;
}
}
我們可以看到,這個方法上有一個@CallerSensitive
注解,所以今天我們就來了解下這個注解儒飒。
分析
查看源碼,我們可以看到方法內(nèi)部都調(diào)用了Reflection.getCallerClass()檩奠,這是一個native方法桩了;
巧的是,這個方法也有@CallerSensitive
注解埠戳,下面是這個方法的源碼:
@CallerSensitive
public static native Class<?> getCallerClass();
解釋
Caller:調(diào)用者井誉,Sensitive:敏感的/易感知的,顧名思義整胃,這是主要針對于方法調(diào)用者所做的一些控制送悔;
然而實際上,@CallSensitive是JVM中專用的注解爪模,在類加載過過程中是可以常常看到這個注解荚藻;
那么屋灌,需要什么權(quán)限才能調(diào)用這個方法?
- 由bootstrap class loader加載的類可以調(diào)用
- 由extension class loader加載的類可以調(diào)用
用戶路徑的類加載都是由 application class loader進(jìn)行加載的应狱,也就是用戶自定義的類基本上是無法調(diào)用此方法的
作用
Reflection.getCallerClass()方法調(diào)用所在的方法必須用@CallerSensitive進(jìn)行注解共郭;
通過此方法獲取class時會跳過鏈路上所有的有@CallerSensitive注解的方法的類;
直到遇到第一個未使用該注解的類疾呻,避免了用Reflection.getCallerClass(int n) 這個過時方法來自己做判斷除嘹;
番外
據(jù)說注解是為了堵住漏洞用的,曾經(jīng)有黑客通過構(gòu)造雙重反射來提升權(quán)限岸蜗,原理是當(dāng)時反射只檢查固定深度的調(diào)用者的類尉咕,看它有沒有特權(quán)胆胰;
當(dāng)你嘗試用反射調(diào)用Reflection.getCallerClass()叔收,結(jié)果會拋出異常型宝;
所以在我們?nèi)粘i_發(fā)中木人,可以說作用不大便监,了解就好了阅束;
主要還是JDK底層控制權(quán)限的地方使用细疚。