回顾一些演示文稿,我遇到了以下主张:当 JVM 加载一个类时,它可以分析其内容并确保操作数堆栈没有溢出或下溢。我发现很多来源都提出了同样的主张,但没有具体说明它是如何完成的。
我不清楚如何使用静态分析进行此类验证。假设我有一个(恶意)方法,它获取一些值作为参数,并使用它来执行一系列弹出。在加载时,迭代次数是未知的,因为它取决于方法调用者给出的参数。因此,在我看来,只有在运行时才能确定是否会出现下溢。我在这里想念什么?
回顾一些演示文稿,我遇到了以下主张:当 JVM 加载一个类时,它可以分析其内容并确保操作数堆栈没有溢出或下溢。我发现很多来源都提出了同样的主张,但没有具体说明它是如何完成的。
我不清楚如何使用静态分析进行此类验证。假设我有一个(恶意)方法,它获取一些值作为参数,并使用它来执行一系列弹出。在加载时,迭代次数是未知的,因为它取决于方法调用者给出的参数。因此,在我看来,只有在运行时才能确定是否会出现下溢。我在这里想念什么?
您可以在Java 虚拟机规范中找到字节码验证器的基本描述。
简单来说,每个分支点的堆栈深度都是已知的,在同一个合并点合并的两条执行路径也必须具有相同的堆栈深度。因此,验证器不允许您在没有相应 put 的情况下执行一系列 pop。
该方法的代码被分成执行块。“块”是无需跳出或跳入即可执行的指令序列。这些块构建所有可能执行路径的有向图。
一个块在其开始时总是期望一定的堆栈大小,并且在其结束时具有固定的堆栈大小(开始 + 所有推送 - 所有弹出)。验证器检查对于可以从给定块“b”到达的所有块“a”,b 的结束堆栈大小与 a 的开始堆栈大小匹配。