sun.reflect.CallerSensitive注释是什么意思?



上述@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

基本上,JVM使用@CallerSensitive注释

JVM将跟踪该注释,并可选地强制执行不变,sun.reflect.Reflection.getCallerClass方法可以只报告一个方法的调用者,当该方法被标记为这个注释。

From jdk.internal.reflect.CallerSensitive

注释了@CallerSensitive的方法对它的调用类敏感,通过反射。

自Java SE 9以来,等效的是java.lang.StackWalker.getCallerClass

这实际上是Java 1.0和1.1版本的安全模型,它们实现了一种乞丐的链接器检查。除了与反射相关的内容外,这是一种连贯的方法,但它非常脆弱。另一方面,更严格的Java 2安全模型是神奇的,并且没有显示其工作原理。

@CallerSensitive方法根据调用它们的类改变行为。这总是令人惊讶,但Java 2堆栈检查安全模型也是如此。更糟糕的是,这些方法调用对于代表其调用者工作的类特别有用,因此上下文无论如何都是错误的。

Java SE的安全编码指南涵盖了这个领域。

  • 指南9-8/ACCESS-8:根据直接调用者的类加载器,安全地调用绕过SecurityManager检查的标准api
  • 指南9-9/ACCESS-9:使用直接调用者的类加载器实例安全地调用执行任务的标准api
  • 指南9-10/access -10:注意对直接调用者执行Java语言访问检查的标准api
  • 指南9-11/ACCESS-11:注意java.lang.reflect.Method.invoke在检查直接调用者时被忽略
  • 指南9-12/ACCESS-12:避免在接口类中使用调用者敏感的方法名

Java SE 9中模块的引入意味着一些细节发生了变化。

另外,如果Method.invoke调用@CallerSensitive方法,getCallerClass会忽略一些堆栈帧。在内部,JDK使用一个"蹦床"ClassLoader作为一个良性的虚拟调用者。java.lang.invoke.MethodHandle复制Method.invoke的问题。AccessController.doPrivileged方法也有问题,规范的结果令人惊讶。

JEP 176:对调用者敏感方法的机械检查处理特定的@CallerSensitive jdk内部注释。指南中的方法列表是由FindBugs插件生成的,但随后手动更新。

相关内容

  • 没有找到相关文章

最新更新