@CallerSensitive
注释放在方法上意味着什么?
例如,在Class的getClassLoader方法中存在该注释。
@CallerSensitive
public ClassLoader getClassLoader() {
//
}
@CallerSensitive
注释放在方法上意味着什么?
例如,在Class的getClassLoader方法中存在该注释。
@CallerSensitive
public ClassLoader getClassLoader() {
//
}
根据我在评论中提供的 JEP(也可在此处找到):
调用者敏感方法根据其直接调用者的类来变化行为。它通过调用
sun.reflect.Reflection.getCallerClass
方法来发现其调用者的类。
如果您查看 Class#forName(String)
的实现:
@CallerSensitive
public static Class<?> forName(String className)
throws ClassNotFoundException {
return forName0(className, true,
ClassLoader.getClassLoader(Reflection.getCallerClass()));
}
你会注意到它使用了Reflection.getCallerClass()
方法。如果我们查看该方法:
返回调用此方法的方法的调用者类,忽略与
java.lang.reflect.Method.invoke()
及其实现相关的框架。
@CallerSensitive
public static native Class getCallerClass();
在这个JEP之前,问题似乎是如果通过反射调用了敏感调用者方法,就必须进行复杂的处理来确定实际的调用类。如果方法是通过反射调用的,这将会有问题。使用@CallerSensitive
引入了一个更简单的过程。
基本上,@CallerSensitive
注解是由JVM使用的。
JVM将跟踪此注解,并可选择强制执行不变式,即当标记了此注解的方法时,
sun.reflect.Reflection.getCallerClass
方法只能报告方法的调用者。
java.lang.reflect.CallerSensitive
注释呢? - Lukas Edersun.reflect.***
这个包只适用于 JVM,而不适用于 JDK。JEP(Java增强提案)中提到这个包的作用之一是为了加强安全性和更好地管理调用者。需要注意的是,该包只能在 JVM 中使用。 - Sotirios Delimanolis来自 jdk.internal.reflect.CallerSensitive
一个被注解为@CallerSensitive的方法对于其调用类是敏感的, 通过Reflection.getCallerClass或等效方式。
等效方式是自Java SE 9以来的java.lang.StackWalker.getCallerClass
。
这实际上是Java版本1.0和1.1的安全模型,它实现了一种类似穷人链接器检查的方法。这是一种连贯的方法,但与反射相关的任何内容都是非常脆弱的。另一方面,更严格的Java 2安全模型是神奇的,不显示其工作方式。
@CallerSensitive
方法根据调用它们的类改变行为。这总是令人惊讶,但Java 2堆栈检查安全模型也是如此。更糟糕的是,这些方法调用对于代表其调用者工作的类特别有用,因此上下文本来就是错误的。
Java SE安全编码指南涵盖了这个领域。
Method.invoke
调用@CallerSensitive
方法,则getCallerClass
会忽略一些堆栈帧。JDK在内部使用“蹦床”ClassLoader
作为良性虚拟调用者。 java.lang.invoke.MethodHandle
复制了Method.invoke
的问题。 AccessController.doPrivileged
方法也存在问题,其规范的后果令人惊讶。JEP 176: Mechanical Checking of Caller-Sensitive Methods处理特定的@CallerSensitive
jdk-internal注释。Guidelines中的方法列表由FindBugs插件生成,但随后进行了手动更新。