如何在JVM中validation字节码?

如何在JVM中validation字节码?

Oracle本身有一些关于它如何工作的片段。

基本上,JRE不信任JDK。 那是因为它不知道哪个JDK编译器创建了类文件。 在validation之前,它会将类文件视为敌对文件。

扩展到这一点,字节码validation是防止Sun称之为“恶意编译器”的必要步骤。 Sun自己的Java编译器确保Java源代码不违反安全规则,但是当应用程序导入代码片段时,它实际上并不知道代码片段是否遵循Java语言规则以确保安全。 换句话说,代码可能不是由值得信赖的Java编译器生成的。

在这种情况下,计算机上的Java运行时系统必须假定片段是坏的并使其进行字节码validation。

在完成此validation过程之前,Java虚拟机甚至看不到字节码。 在加载字节码时执行此操作还具有以下优点:每次执行代码时都不需要执行大量的运行时检查。 因为它已被validation为正确,所以它一旦开始运行就可以比其他方式运行得更快。

链接图的再现如下:

<<<=== Unsafe / Safe ===>>> \ +---------------+ +-------------------+ | Java source | +--> | Class loader | --+ +---------------+ | | Bytecode verifier | | | | +-------------------+ | V | / | +---------------+ | \ V | Java compiler | Network / +-------------------+ +---------------+ | \ | JVM/JIT | | | / +-------------------+ V | \ | +---------------+ | / V | Java bytecode | --+ \ +-------------------+ +---------------+ / | Operating system | \ +-------------------+ / | \ V / +-------------------+ \ | Hardware | / +-------------------+ \ <<<=== Unsafe / Safe ===>>> 

最好的信息来源可能是JVM规范中的相关部分, 4.10类文件的validation 。

有关详细信息,请参阅链接,但广泛地说:

链接时validation可以提高解释器的性能。 可以消除否则必须执行的昂贵检查以在运行时validation每个解释指令的约束。 Java虚拟机可以假定已经执行了这些检查。 例如,Java虚拟机已经知道以下内容:

  • 没有操作数堆栈溢出或下溢。
  • 所有本地变量使用和存储都是有效的。
  • 所有Java虚拟机指令的参数都是有效类型。

validation程序还执行validation,无需查看代码属性的代码数组(第4.7.3节)即可完成validation。 执行的检查包括以下内容:

  • 确保最终类不是子类,并且不会覆盖最终方法(第5.4.5节)。
  • 检查每个类( Object除外)是否具有直接超类。
  • 确保常量池满足记录的静态约束; 例如,常量池中的每个CONSTANT_Class_info结构在其name_index项中包含CONSTANT_Class_info结构的有效常量池索引。
  • 检查常量池中的所有字段引用和方法引用是否具有有效名称,有效类和有效类型描述符。