跳到主要内容

JEP 176:调用者敏感方法的机械检查

概括

通过用准确识别此类方法并允许可靠地发现其调用者的机制替换现有的手工维护的调用者敏感方法列表,提高 JDK 方法句柄实现的安全性。

非目标

拟议的@CallerSensitive注释可能对其他类型的分析或审计有用,但此类活动超出了本 JEP 的范围。

为非系统代码提供公共 API 也不是目标。

描述

调用_者敏感的方法_根据其直接调用者的类来改变其行为。它通过调用该方法来发现其调用者的类sun.reflect.Reflection.getCallerClass

大多数对调用者敏感的方法以某种方式充当调用者的代理。当通过反射调用时,必须对这些方法进行特殊处理,以确保该getCallerClass方法返回实际调用者的类,而不是反射机制本身的某个类。执行此操作的逻辑涉及与手动维护的调用者敏感方法列表进行模式匹配,该列表很脆弱且难以维护。

为了改进这一点,我们将使用内部注释来标记 JDK 中所有调用者敏感的方法@sun.reflect.CallerSensitive。 JVM 将跟踪此注释,并且可以选择强制执行以下不变量:sun.reflect.Reflection.getCallerClass当该方法标记有此注释时,该方法只能报告该方法的调用者。 JVM 将在解析 MemberName 时设置一个新的调用者敏感位,并且包私有方法java.lang.invoke.MethodHandleNatives.isCallerSensitive将升级为直接查询它,而不是查阅方法名称列表。

@CallerSensitive注释可能对其他目的有用,例如跟踪新的调用者敏感方法的引入或在方法中提供类似的特殊处理sun.reflect.misc.MethodUtil.invoke

JDK 中有两个地方的方法可以检查其直接调用者之外的堆栈帧。我们建议进行以下更改,以便可靠地执行调用者敏感性检查:

  • 弃用该SecurityManager.checkMemberAccess方法,以期在未来版本中将其更改为无条件抛出异常。该checkMemberAccess方法要求调用者的框架的堆栈深度为四,这是脆弱且难以强制执行的。

  • 修改java.util.logging.Logger为不要遍历堆栈来搜索资源包。此堆栈遍历旨在作为临时措施,以允许容器过渡到使用上下文类加载器。它已被指定在未来版本中删除。

备择方案

@CallerSensitive如上所述添加注释,但仅使用它来验证手动维护的方法列表。这种替代方案将是一种改进,但在运行时检查注释更可靠。

测试

现有的测试套件将很好地充当此功能的积极测试用例。需要新的负面测试用例来识别未正确标记的调用者敏感方法。

风险和假设

此更改可能会带来副作用,但风险很小。我们假设已经计划的 JDK 8 广泛测试将发现任何此类问题。

影响

  • 性能:我们预计性能影响可以忽略不计。 JVM 已经在解析 JSR 292 的运行时方法注释,并且与昂贵的堆栈遍历操作相比,该检查相对便宜。

  • 兼容性:依赖于类的堆栈遍历行为的应用程序Logger将不再工作。