前言
在阅读Unsafe源码是,以下是Unsafe部分源码:
@CallerSensitive
public static Unsafe getUnsafe() {
Class var0 = Reflection.getCallerClass();
if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
throw new SecurityException("Unsafe");
} else {
return theUnsafe;
}
}
我们可以看到,这个方法上有一个@CallerSensitive
注解,所以今天我们就来了解下这个注解。
分析
查看源码,我们可以看到方法内部都调用了Reflection.getCallerClass(),这是一个native方法;
巧的是,这个方法也有@CallerSensitive
注解,下面是这个方法的源码:
@CallerSensitive
public static native Class<?> getCallerClass();
解释
Caller:调用者,Sensitive:敏感的/易感知的,顾名思义,这是主要针对于方法调用者所做的一些控制;
然而实际上,@CallSensitive是JVM中专用的注解,在类加载过过程中是可以常常看到这个注解;
那么,需要什么权限才能调用这个方法?
- 由bootstrap class loader加载的类可以调用
- 由extension class loader加载的类可以调用
用户路径的类加载都是由 application class loader进行加载的,也就是用户自定义的类基本上是无法调用此方法的
作用
Reflection.getCallerClass()方法调用所在的方法必须用@CallerSensitive进行注解;
通过此方法获取class时会跳过链路上所有的有@CallerSensitive注解的方法的类;
直到遇到第一个未使用该注解的类,避免了用Reflection.getCallerClass(int n) 这个过时方法来自己做判断;
番外
据说注解是为了堵住漏洞用的,曾经有黑客通过构造双重反射来提升权限,原理是当时反射只检查固定深度的调用者的类,看它有没有特权;
当你尝试用反射调用Reflection.getCallerClass(),结果会抛出异常;
所以在我们日常开发中,可以说作用不大,了解就好了;
主要还是JDK底层控制权限的地方使用。
网友评论