有人可以列出字节码验证器为保证程序正确性必须执行的主要任务吗? JVM 规范中是否定义了标准的、最小的职责集?我还想知道验证是否跨越其他阶段,例如加载和初始化。
这是在 JVM 规范:第 4.10 章中指定的。验证类文件 .
页面的大部分内容描述了类型安全的各个方面。为了检查程序是否类型安全,验证程序需要找出每个程序点的操作数堆栈中驻留的操作数类型,并确保它们与相应指令期望的类型匹配。
其验证的其他事项包括但不限于以下内容:
分支必须位于方法的代码数组的范围内。
所有控制流指令的目标都是指令的开始。在宽指令的情况下,宽操作码被认为是指令的开始,并且给出由该宽指令修改的操作的操作码不被认为是指令的开始。不允许分支到指令中间。
没有指令可以访问或修改索引大于或等于其方法指示它分配的局部变量数量的局部变量。
对常量池的所有引用都必须是适当类型的条目。 (例如,指令 getfield 必须引用一个字段。)
代码不会在指令中间结束。
执行不能脱离代码末尾。
对于每个异常处理程序,受处理程序保护的代码的起始点和结束点必须位于指令的开头,或者在结束点的情况下,紧接着代码的末尾。起点必须在终点之前。异常处理程序代码必须从有效指令开始,并且不能从被宽指令修改的操作码开始。
作为最后一步,验证器还执行数据流分析,这确保没有指令引用任何未初始化的局部变量。
或者,您可能想查看 James Gosling 撰写的 Java 语言环境 白皮书。
[
字节码验证器遍历字节码,构造类型 状态信息,并验证所有参数的类型 字节码指令。
图示展示了Java语言的数据流和控制流 源代码通过Java编译器,到类加载器 字节码验证器,然后进入 Java 虚拟机, 包含解释器和运行时系统。重要的问题是 Java 类加载器和字节码验证器不做任何事情 关于字节码流的主要来源的假设——代码 可能来自本地系统,或者可能已经传输了一半 环绕地球。字节码验证器充当某种看门人的角色: 它确保传递给 Java 解释器的代码处于合适状态 被执行并且可以运行而不用担心破坏Java 口译员。导入的代码不允许以任何方式执行 直到通过验证者的测试。一旦验证者 完成后,我们知道了许多重要的属性:
- 没有操作数堆栈上溢或下溢
- 已知所有字节码指令的参数类型始终是正确的
- 已知对象字段访问是合法的——私有、公共或受保护
虽然所有这些检查看起来都极其详细,但到了 字节码验证器已经完成了它的工作,Java解释器可以 继续,知道代码将安全运行。知道这些 属性使 Java 解释器更快,因为它不 必须检查任何东西。没有操作数类型检查,也没有堆栈 溢出检查。因此,口译员可以全速运行 不影响可靠性。
它执行以下操作:
参考: http://java.sun.com/docs/white/langenv/Security.doc3.html