JVM字节码验证程序的职责

Bob*_*r02 19 java jvm

有人可以列出字节码验证器必须执行的主要任务,以保证程序的正确性吗?JVM规范中是否定义了一组标准的最小职责?我还想知道验证是否跨越其他阶段,如加载和初始化.

aio*_*obe 16

这在JVM规范中指定:第4.10章.验证类文件.

该页面的大部分内容描述了类型安全的各个方面.要检查程序是否类型安全,验证程序需要确定每个程序点的操作数堆栈中驻留的操作数类型,并确保它们与相应指令所期望的类型相匹配.

它验证的其他内容包括但不限于以下内容:

  • 分支必须在方法的代码数组的范围内.

  • 所有控制流指令的目标都是指令的开始.在宽指令的情况下,宽操作码被认为是指令的开始,并且给予由该宽指令修改的操作的操作码不被认为是开始指令.不允许分支到指令的中间.

  • 没有指令可以访问或修改索引大于或等于其方法指示它分配的局部变量数的局部变量.

  • 对常量池的所有引用必须是相应类型的条目.(例如,指令getfield必须引用一个字段.)

  • 代码不会在指令中间结束.

  • 执行不能脱离代码的末尾.

  • 对于每个异常处理程序,由处理程序保护的代码的起始点和结束点必须位于指令的开头,或者在结束点的情况下,紧接在代码的结尾之后.起点必须在结束点之前.异常处理程序代码必须从有效指令开始,并且它不能从宽指令修改的操作码开始.

作为最后一步,验证程序还执行数据流分析,确保没有指令引用任何未初始化的局部变量.


Edw*_*rzo 7

另外,您可能想看看James Gosling撰写的Java语言环境白皮书.

在此输入图像描述

字节码验证器遍历字节码,构造类型状态信息,并验证所有字节码指令的参数类型.

该图显示了从Java语言源代码到Java编译器,到类加载器和字节码验证器以及因此包含解释器和运行时系统的Java虚拟机的数据和控制流.重要的问题是Java类加载器和字节码验证器没有对字节码流的主要来源做出任何假设 - 代码可能来自本地系统,或者它可能已经绕过地球一半.字节码验证器充当一种网守:它确保传递给Java解释器的代码处于适合的状态以便执行并且可以运行而不用担心破坏Java解释器.在通过验证程序的测试之前,不允许以任何方式执行导入的代码.完成验证程序后,会知道许多重要属性:

  • 没有操作数堆栈溢出或下溢
  • 已知所有字节码指令的参数类型总是正确的
  • 已知对象字段访问是合法的 - 私有,公共或受保护

虽然所有这些检查看起来都非常详细,但是当字节码验证器完成其工作时,Java解释器可以继续进行,因为知道代码将安全运行.了解这些属性会使Java解释器更快,因为它不需要检查任何内容.没有操作数类型检查和堆栈溢出检查.因此,解释器可以全速运行而不会影响可靠性.