跳转到内容

J2ME 编程/MIDlet 预验证

来自维基教科书,开放世界中的开放书籍

一个MIDlet 是一个用于嵌入式设备的Java 程序,更具体地说,是用于J2ME 虚拟机。通常,这些是运行在手机上的游戏和应用程序。

由于J2SE 中的类验证占用 50 KB,而MIDP 设备的存储空间有限,因此类验证已分解为由开发人员完成的部分和由移动 JVM 本身完成的部分。由开发人员引导的类验证阶段称为 MIDlet 预验证,它发生在类编译之后。

预验证完成的任务

[编辑 | 编辑源代码]

通常,预验证任务用注释标记类文件,这些注释由移动 VM 中的小型不完整类验证器读取并使用,以执行快速类验证,从而使移动 VM 能够运行生成的字节码。生成的字节码 是有效的字节码,因为注释使用字节码的属性来为移动 VM 生成注释,以便它在执行最终不完整类验证时进行读取。[1]

JVM 类文件验证

[编辑 | 编辑源代码]

根据 Java 虚拟机规范[2],类文件验证在 JVM 完全启动之前完成,以运行应用程序的字节码。

第 1 步

[编辑 | 编辑源代码]
  • 前四个字节中的魔数正确。
  • 字节码属性必须具有适当的长度。
  • 类文件不能被截断或在末尾有额外的字节。
  • 常量池不得包含任何表面数据。

第 2 步

[编辑 | 编辑源代码]
  • 确保最终类不会被子类化,并且最终方法不会被重写。
  • 检查除 Object 之外的每个类是否都有一个直接超类。
  • 确保常量池满足记录的静态约束。
  • 检查常量池中所有字段引用和方法引用是否具有有效的名称、有效的类和有效的类型描述符。

第 3 步

[编辑 | 编辑源代码]

在链接期间,验证器通过执行数据流分析来检查代码属性的代码数组,以确保以下项目为真:

  • 操作数堆栈始终保持相同的大小并包含相同类型的值。
  • 除非已知局部变量包含适当类型的值,否则不会访问它。
  • 方法使用适当的参数调用。
  • 字段仅使用适当类型的赋值。
  • 所有操作码 在操作数堆栈和局部变量数组中都有适当的类型参数。

第 4 步

[编辑 | 编辑源代码]

这是类加载发生的步骤,以完成类验证过程。

预验证步骤

[编辑 | 编辑源代码]
  • 预验证放置一个 StackMap 属性,它是 Code 属性的子属性,它描述了使用的变量类型和操作数堆栈项。
  • 内联所有子例程并移除跳转。[3]
  • 默认情况下,它为 Java 代码生成一个类文件。[4]

预验证通过在 Code 属性的 StackMap 部分插入描述使用的变量类型和操作数堆栈项的注释来预验证已编译的类。这以及内联所有子例程和移除跳转,将 J2SE 验证过程的前三个步骤简化为更易于管理的步骤,从而在移动设备中完成最后第四步,以在移动 JVM 内完成移动设备的内存大小。

商标声明

[编辑 | 编辑源代码]

J2ME、Java 和所有基于 Java 的商标是ORACLE 在美国和其他国家/地区的商标或注册商标。

参考文献

[编辑 | 编辑源代码]
  1. "什么是预验证?". 什么是预验证?为什么我在没有预验证类文件时从 CLDC/KVM 中收到错误消息?.
  2. "VM Spec". Java 虚拟机规范. ISBN 0201432943
  3. ("无处不在的服务" (PDF). 移动设备上的无处不在的服务.
  4. "J2ME 教程,第一部分:创建 MIDlet?". 默认情况下,预验证器将在当前目录中的名为 output 的文件夹中创建预验证版本的类文件。它将保留包结构…….

另请参阅

[编辑 | 编辑源代码]
  • "什么是预验证?". 什么是预验证?当我未对我的类文件进行预验证时,为什么我会收到来自 CLDC/KVM 的错误消息?.
华夏公益教科书