第 2部分 JAVA 卡技术
第 3章 Java卡技术概述
Java卡技术能够使利用 Java 编程语言写的程序在智能卡上和其它资源有限的设备上运行。
本章将对 Java 卡技术-系统体系结构及其组成部分作一概括描述。
3.1 体系结构概述
智能卡代表现今使用的最小的计算平台。智能卡的存储器配置例如可以是:1K RAM, 16K
EEPROM, 和 24K ROM。Java 卡技术设计的最大挑战是:要把 Java 系统软件放到智能卡上,
同时还要为应用保留足够的空间。解决这个问题的办法是只支持 Java 语言特性的子集和采用分
离模式的 Java 虚拟机。
Java 卡虚拟机被分割成两个部分:一部分运行于卡外,而另一部分运行于卡上。许多不限于
运行时执行的处理任务,例如类的 loading,字节码验证,地址确定与链接,以及优化等,由于运
行于卡外的虚拟机来处理,在那里资源通常不必关心。
智能卡在许多方面不同于台式计算机。除了支持Java语言外,Java 卡技术还定义了一个运行
时环境,这个环境支持智能卡存储器、通信、安全,和应用执行模式。Java 卡运行时环境符合智
能卡国际标准 ISO 7816。
Java卡运行环境的最重要的特性就是把智能卡操作系统和应用清晰地分离开来。运行环境将
底层的复杂性和智能卡系统的细节封装起来。应用通过清晰定义的高级编程接口请求系统服务和
资源。
因此,Java 卡技术实质上乃定义了这样一个平台:在这个平台上,用Java编程语言写的应用
能够在智能卡中和其它资源有限的设备上运行。(为 Java 卡平台写的应用称为 applets.)。因为分
离的虚拟机体系结构,该平台从时空角度,乃分布于智能卡和台式机之间。Java 卡技术由三个部
分组成,各于一个规范中定义。
z Java 卡 2.1 虚拟机 (JCVM) 规范:定义 Java 程序设计语言子集和适合于智能卡应用
的虚拟机定义。
z Java 卡运行时环境(JCRE)规范:精确地描述了Java 卡的运行时行为, 包括存储管理、
applet管理,和其它运行时特性。
z Java 卡 2.1 应用编程接口(API) 规范:描述了编程 Java 卡应用的核心与扩展 Java 包
和类。
3.2 Java 卡语言子集
因为它的存储空间之小,Java 卡平台只能支持Java语言特性的一个经过精心挑选的、定制的
子集。 这个子集包括的特性非常适合为智能卡和其它小型设备编写的程序,而却保持了 Java 编
程语言的面向对象的能力。表3.1 着重给出了某些重要的支持的和不支持的 Java 语言特性。
把那些不支持的特性的 keywords 也省略了,这是不足为怪的。许多高级的 Java 卡提供垃
圾收集机制,使对象删除成为可能。
附录 A 提供了 Java 卡语言子集的详尽注释。关于需要存储和操作大数的 Java 卡 applets,
14章提供了在不使用大的基本数据类型的前提下处理大数的编程提示。
表 3.1 支持的和不止持的Java 特性
Supported Java Features Unsupported Java Features
• 小的基本数据类型: boolean,byte, short
•一维数组
•Java包, 类,接口, 和例外
• Java 面向对象的特性:继承,虚拟机,重载和
动态数据对象建立,访问域,以及约束规则
• int keyword 和32-位bit 整数数据类型支持
是任选的。
• 大的基本数据类型: long,double, float
• 字符和字符串
• 多维数组
• 动态类装载
•安全管理器
• 垃圾收集和 finalization
• 线程
• 对象串行化
•对象cloning
3.3 Java 卡虚拟机
Java 卡虚拟机(JCVM) 和Java虚拟机(JVM)之间的一个主要差别在于JCVM 是作为两个分立
的部分实现的,如图3.1所示。Java 卡虚拟机的卡上部分包括 Java 卡字节码解释器。而 Java 卡
转换器运行于PC或工作站。转换器是虚拟机的卡外部分。卡上和卡外部分一起实现了虚拟机的全
部功能,包
图 3.1 Java 卡虚拟机
括 loading Java 类文件和按特定的语意执行之。转换器装载与预处理构成 Java 包的类文件和输
出 CAP (converted applet) 文件。而后将 CAP 文件装载到 Java 智能卡中并有解释器执行。除了
建立 CAP 文件之外,转换器还生成一个表示正北转换的包的公共 APIs 的输出文件。
Java 卡技术只支持Java 语言的子集。相应地,Java 卡虚拟机也只支持那些由该语言子集需
要的特性。转换器将删除那些在 applet 中使用的不支持的语言特性。
3.3.1 CAP 文件和 Export 文件
Java 卡技术引入两种新的二进制文件格式,它们使 Java 卡软件平台无关地进行开发、发布
和执行。一个 CAP文件包含一个Java包中的类的可执行的二进制表示。JAR 文件格式用作 CAP
文件的 container 格式。一个 CAP 文件对应一个包含其诸成分集合的 JAR 文件,每个成分为该
JAR 文件中的一个文件。每个成分描述CAP文件内容的一个方面,例如类信息、可执行的字节码、
链接信息、验证信息,等等。CAP 文件的格式是针对小型化的设备,利用紧缩的数据结构和有限
的间接而被优化了。它定义了一个字节码指令集,该指令集基于 Java 字节码指令集,并对其进
行了优化。
Java 程序的 “写一次,到处运行” 的品性或许是 Jav 平台的最重要特性。在 Java 技术中,
类文件是 Java 体系结构的中心部分,它定义了 java 平台二进制兼容性的标准。因为 Java 卡系
统体系结构的分布式特点,CAP 文件建立了关于 Java 卡平台的二进制兼容性的标准文件格式。
CAP 文件格式就是把软件装载到 java 卡上的形式。例如,CAP 文件能够在卡片做好之后,动
态地装载 applet 类。 这就是其得名 CAP (converted apple) 文件的原因所在。
Export 文件不被装载到智能卡上并且不被解释器直接使用,而它们是由转换器产生并用于验
证和链接过程。可将 Export 文件视为C编程语言中的头文件。一个 export 文件包含一个包的公
共的 API。它定义类的访问域(scope)与名字和方法的访问域与签名,以及类的域(fields)。
一个 export 文件还包含用于卡上包间的 resolving 的链接信息。
export 文件不包含任何关于实现的信息,即不含字节码。所以,一个 export 文件可由applet
开发者自由发布给该 applet 的潜在用户,而不会泄露内部实现细节。
3.3.2 Java 卡 转换器(Converter)
不像 Java 虚拟机(一次处理一个类),转换器的转换单位是一个包。编译器由源代码产生
类文件,而后转换器预处理构成一个 java 包的全部类文件,并将这个包转换为一个 CAP 文件。
在转换过程中,转换器执行桌面环境下Java虚拟机在装载类时所完成的任务:
z 验证Java类的装载映像格式无误
z 检查Java卡语言子集是否违例
z 完成静态变量的初始化
z 将对类、方法和域的符号引用解析为可在卡上有效处理的更紧凑的形式
z 利用在类装载与链接时获得的信息优化字节码
z 分配存储空间和建立表示类的虚拟机数据结构
转换器不仅把类文件作为转换的输入,输入还可能包括一或多个 export 文件。除了产生一
个 CAP 文件外,转换器还产生一个关于被转换包的 export 文件。图 3.2 表明一个包是如何被
转换的。转换器装载一个Java包中的全部类。如果该包输入来自其它包的类,转换器还将装载这
些包的 export 文件。转换器的输出是一个CAP 文件和一个正被转换的包的 export 文件。
图 3.2 转换一个包
3.3.3 Java 卡 解释器(Interpreter)
Java 卡解释器提供 Java 语言模型的运行时支持,因此允许 applet 代码与硬件无关。解释器
执行下列任务:
z 执行字节码指令并最终执行 applets
z 控制存储分配和对象建立
z 在保证运行时安全中扮演重要角色
至此,Java 卡虚拟机已经被描述为由转换器和解释器组成。然而,在我们目前的定义中非正
式地把 Java 卡虚拟机被定义为该虚拟机的卡上部分――解释器。这一习惯已经用于许多早期的
Java卡出版物中。因此,本书后面的部分将会同时使用“Java 卡解释器”和“Java 卡虚拟机”这
两个词,除非另外说明。但是,在比较 Java 卡平台和 Java 平台时,读者应知道执行 Java 类文
件的功能是由转换器和解释器二者一起完成的。
3.4 Java 卡 Installer 和卡外安装程序
Java 卡解释器本身并不装载 CAP 文件,它只执行在 CAP 文件中发现的代码。在 Java 卡
技术中,下载和安装 CAP 文件的机制乃包含在一个称为安装器(installer)的部件中。
Java 卡安装器驻留在卡片中,它与卡外的一个安装程序协同工作。该卡外安装程序通过卡片
接收设备(CAD),将CAP文件中的可执行的二进制代码传送给在卡上运行的安装器。安装器把二
进制代码写入智能卡存储器中,将其与已经放在卡片上的其它类进行链接,并建立和初始化由Java
卡运行时环境内部使用的任何数据结构。安装器和安装程序以及它们如何与 Java 卡平台的其余
部分相关联示于图3.3。
解释器和CAP文件安装器间功能的拆分使得解释器保持较小,并且提供安装器实现的灵活性。
关于安装器的更多的解释在本章后头的 applet 安装中给出。
PC或工作站
图 3.3 Java 卡安装器和卡外安装程序
3.5 Java 卡运行时环境
Java 卡运行时环境(JCRE) 由运行于智能卡中的一些 Java 卡系统组件构成。 JCRE 负责卡
片资源管理、网络通信、applet 执行,和卡上系统与 applet 的安全。因此,它实际上充当智能卡
操作系统的角色。
如图3.4所示,JCRE 位于智能卡硬件和 native 系统的顶上。JCRE 由 Java 卡虚拟机(字节码
解释器)、Java 卡应用架构类(APIs)、业界专用扩展,以及一些 JCRE 系统类组成。JCRE 很好地
将 applets 和智能卡厂商的专用技术隔离开来,并为 applets 提供标准的系统和API 接口。因此,
applets 很容易写和在各种不同的智能卡体系结构上移植。
JCRE 的底层包含Java 卡虚拟机(JCVM)和一些 native 方法。 JCVM 执行字节码、控制存
储器分配、管理对象,和保证执行的安全性,如前所述。native 方法提供对 JCVM 和上层系统
类的支持。它们负责处理低级通信协议、存储管理、cryptographic 支持等。
Applets
JCRE
智能卡硬件和Native 系统
优惠应用 钱包应用 认证应用
业界专用扩展 安装程序 架构类(APIs)
Applet 管理 事物管理 I/O网络通信 其它服务
Java 卡虚拟机
(字节码解释程序)
Native 方法
图 3.4 卡上系统的体系结构
系统类作为 JCRE 执行程序。这些类是对操作系统核心的模拟。系统类负责管理事物、管理
host 应用1
和 Java 卡 applets 之间的通信,以及控制 applet 的建立、选择,和 deselection。为
了完成这些任务,系统类一般地要调用 native 方法。
Java 卡应用架构定义了应用编程接口。这个架构由四个核心 API 包和一个扩展 API 包组
成。这些 API 类是很紧凑的,并且是专门为开发智能卡 applets 而定制的。 该架构的主要优点
在于使得一个 applet 的建立变得容易了。于是,applet 开发者的主要精力可其集中在其 applet
的细节上,而不是智能卡系统基础设施的细节上。Applets 通过API 类访问 JCRE 的服务。
各行业可以提供扩充库,以提供附加的服务或改善安全和系统模型。例如,Open Platform 扩
展了JCRE 的服务,以满足金融界专门的安全要求。在许多追加的特性中,强制了发卡行对卡片
的控制并规定了卡片个人化的标准命令集。
卡上安装程序能够保证在卡片生产完毕并发行给持卡人之后,软件和 applets 能够安全地下
载到卡片中。卡上安装程序和卡外安装程序协同操作,它们共同完成 CAP 文件的二进制内容的
下载任务。卡上安装程序是一个任选的 JCRE 组成部分。在没有卡上安装程序的时候,所有的卡
片软件(包括applets)都必须在卡片制造过程中写到卡片的存储器中。
Java 卡 applets 是 Java卡平台上的用户程序。当然,applets 是利用 Java 编程语言的的子集
编写的,并由 JCRE 进行控制和管理。Applets 可在 Java 智能卡制造好之后再加载到卡上。
3.5.1 JCRE 生命周期
在PC或工作站中,Java 虚拟机是作为一个操作系统进程运行的。数据和对象被建立于 RAM
之中。当该 OS 进程被终止的时候,Java 应用及其对象被自动地废弃。
在Java 智能卡中,Java 卡虚拟机在Java卡运行时环境中运行。JCRE 于卡片初始化时被初始
化。在整个卡片生命期中,JCRE 仅被初始化一次。在这个过程中,JCRE 初始化虚拟机并建立
提供 JCRE 服务和管理 applets 的对象。在安装 applers 的时候,JCRE 建立 applet 实例,而
applets 建立存储数据的对象。
智能卡上的大多数信息即使在卡片断电的时候都必须被保留下来。我们可利用永久存储器技
术(例如EEPROM)来实现这一保持数据的目的。数据和对象被建立于永久存储器中。JCRE 的
生命期相当于整个卡片的生命期。当去电的时候,虚拟机只是被挂起。JCRE 和在卡片上建立的
对象的状态则被保留下来。
下次卡片上电的时候,JCRE 通过从永久存储器2
装载数据而重新启动虚拟机执行。这里一
个微妙的概念是 JCRE 并非恰好从掉电时的断点来继续虚拟机的操作。而是虚拟机被复位,并从
主循环的开头执行。JCRE 复位与初始化不同,因为它要保留在卡片上建立的 applets 和对象。
在复位期间,如果某个事物在之前未完成,JCRE 将进行任何必要的清楚工作,使JCRE 呈一致
的状态。
3.5.2 在一个 CAD Session 中 JCRE如何工作?
从卡片插入卡片接受设备(CAD)并加电至卡片从 CAD 拔出的时间段称为一个 CAD 会话期
(session)。在 CAD 会话期中,JCRE 像普通智能卡一样地操作—它支持与 host 应用的 APDU
I/O 通信(图 3.5).。APDUs (应用协议数据单位)是在 applets 和 host 应用之间交换的数据包。每
一个 APDU 或者包含从 host 至 applet 的命令或者从 applet 至 host 的响应。
在 JCRE 复位之后,JCRE 便进入一个循环,等待来自 host 的 APDU 命令。 host 通过卡
片的输入/输出触点提供的串行通信接口向 Java 卡平台发送 APDU 命令。
图 3.5 APDU I/O 通信
当一条命令到来的时候,JCRE 或者按照该命令的指示,选择一个 applet ,或者将接收到的
命令继续交给当前已经被选择的 applet。而后,被选择的 applet 取得控制,并处理该 APDU 命
令。
在结束的时候,该 applet 向 host 应用发送响应并把控制交还给JCRE。在下一条命令到来的
时候,又重复这一过程。Applets 如何处理 APDUs 将于第7和第 8 章中予以说明。
3.5.3 Java 卡运行时特性
除了支持 Java 语言的运行时模式之外,JCRE 还支持三种附加的运行时特性:
z 永久和临时对象—按缺省,Java 卡对象是永久的并被建立于永久存储器中。这种对象的
空间与数据跨 CAD 会话期。因为安全性与性能的原因,applets 也可在 RAM 中建立
对象,这样的对象称为临时对象。临时对象包含非永久的,不跨 CAD 会话期的临时数
据。
z 原子操作与事物— Java 卡虚拟机保证每次向一个对象或类中的一个域的写操作是原子
的。被修改的域或者取得新值或者被恢复为原先的值。另外,JCRE 还提关于供事物的
APIs。 Applet 可将若干写操作置于一个事物之中。要么一个事物中的全部修改都被完成,
要么(如果在该事物当中发生错误)什么都不作。
z Applet防火墙与共享机制 — applet 防火墙将各 applets 隔离开来。每个 applet 运行于一
个指定的空间之内。 一个 applet 的存在与操作对卡片上其它 applets 不会有影响。 applet
防火墙在 Java 卡虚拟机执行字节码的时候被强制。在 applets 需要共享数据或访问
JCRE 服务的场合,虚拟机通过安全的共享机制来满足这些功能。
3.6 Java 卡APIs
Java 卡 APIs 是由一些为根据 ISO 7816 模式编程智能卡应用而定制的类组成的。APIs 包
含三个核心包和一个扩展包。三个核心包是:java.lang、javacard.framework,和
javacard.security。扩展包是javacardx.crypto。
熟悉 Java 平台的开发者会注意到许多 Java 平台的类在 Java 卡 APIs 中并不被支持。例
如,Java 平台的关于 GUI 接口、网络 I/O,和 台式机文件系统 I/O 的类并不被支持。其原因
在于智能卡没有显示器,并且它们使用不同的网络协议以及文件系统结构。另外,也不支持许多
Java平台的实用程序类,以满足特定的存储器需求。
在 Java 卡 APIs 中的类是紧凑而简明的。它们包括一些为了提供 Java 语言支持和密码技
术服务而根据 Java 平台改编的类。它们还包括一些为支持智能卡 ISO 7816 标准而专门建立的
类。
3.6.1.java.lang 包
Java 卡的 java.lang 包是其 Java 平台上的对应包 java.langpackage 的严格子集。该包所支
持的类是 Object, Throwable,和某些与机器有关的例外类,如表 3.2 所示。对于所支持的类,
许多 Java 方法是不能用的。例如,Java 卡 Object 类 只定义了缺省的构造方法和 equals 方
法。
java.lang 包提供基本的 Java 语言支持。类 Object 为 Java 卡类层次结构定义了一个根,
而类 Throwable 为所有的例外提供了一个共同的祖先。所支持的例外类保证在由于 Java 语言
违例而导致错误发生时有一致性的语意。例如,当访问一个空引用时,Java 虚拟机和 Java 卡虚
拟机都抛出一个 NullPointerException 例外。
Table 3.2 Java 卡java.lang 包
Object Throwable Exception
RuntimeException ArithmeticException ArrayIndexOutOfBoundsException
ArrayStoreException ClassCastException IndexOutOfBoundsException
NullPointerException SecurityException NegativeArraySizeException
3.6.2.javacard.framework 包
javacard.framework 是一个重要的包。 它为 Java 卡 applet 的核心功能提供了架构类和
接口。最重要的是它定义了一个基础 Applet 类,后者为 applet 的执行和其生命期内与 JCRE 的
交互提供了一个框架。它在面对 JCRE 所扮演的角色方面,类似于 Applet 类面对 host 浏览器
时的角色。一个用户 applet 类必须从基类 Applet 扩展而来,并且重写 Applet 类中的方法以实
现该 applet 的功能。
javacard.framework 包中的另一个重要的类是 APDU 类。APDUs 由传输协议传送。两个
标准的传输协议是 T=0 和 T=1。 APDU 类设计得与传输协议无关。换言之,它是被精心设计
的,从而使 applet 的开发者感觉不到 T=0 和 T=1 协议的复杂性以及它们之间的差异。Applet
开发者可利用 APDU 类中提供的方法极其容易地处理 APDU 命令。不管平台支持的底层传输
协议为何,Applets 都能正确地工作。在第 8 章中将说明如何使用 APDU 类。
Java卡平台不支持 Java 平台的类 java.lang.System 。 Java 卡平台包含一个提供与系统性能
相关的接口类 javacard.framework.JCSystem 。JCSystem 类包括控制 applet 执行、资源管
理、事物管理,以及 Java 卡平台上 applet 间对象共享的方法集。
javacard.framework 包中支持的其它类是 PIN,实用程序,和例外。PIN 是个人标识号
(personal identification number)的简称。它是为了认证持卡人而在智能卡中使用的最普通的口令
形式。
3.6.3.javacard.security 包
javacard.security 包 提供关于Java卡平台上支持的密码功能的架构。它的设计基于包
java.security。
javacard.security 包 定义了一个密钥工厂类 keyBuilder 和描述用于对称(DES)或非对称
(DSA 和 RSA)算法中的密码技术密钥的各种接口。此外,它还支持抽象的基类 RandomData、
Signature,和 MessageDigest,后者用于生成随机数数据和计算报文摘要与签名。
3.6.4.javacardx.crypto 包
javacardx.crypto 包是一个扩展包。它包含受制于美国出口条例要求的密码技术类和接口。
javacardx.crypto 包定义关于支持加密和解密功能的抽象基类 Cipher 。
包 javacard.security 和 javacardx.crypto 定义 applets 调用请求密码技术服务的 API
接口。然而,它们并未提供任何实现。一个 JCRE 提供者需要提供这些密钥接口的类并继承抽
象类 RandomData, Signature, MessageDigest,和 Cipher。通常,卡片上有一个独立的协处理器
来完成密码技术有关计算。第10章将解释如何利用包 javacard.security 和 javacardx.crypto
中的类支持 applets 中的密码技术功能。
3.7 Java 卡Applets
不要就因为 Java 卡 applets 和 Java applets 名字都叫 applet,而将二者相混淆。一个 Java
卡 applet 是一个要遵守一组约束的 Java 程序,只允许它运行于 Java 卡运行时环境中。一个
Java 卡 applet 不会在一个浏览器环境中运行。为 Java 卡应用取名 applet 的原因在于在卡片已
经制造好之后,仍能够将 Java 卡 applets 装载到 Java 卡运行时环境中。即,不像在许多嵌入式
系统中那样,不需要在制造阶段将 applets 烧到ROM中。而是,在以后的某时刻,能将它们动态
地下载到卡片中。
一个 applet 类必须从 javacard.framework.Applet 类扩展而来。基类 Applet 是驻留在
Java卡中的所有 applets 的超类。这个 applet 类是定义一个 applet 中的变量和方法的模板。一个
正在卡片上运行的 applet 是一个 Applet 实例 — 该 applet 类的一个对象。像任何永久对象一
样,一个 applet 实例一旦被建立,它就会永久存活在卡片上。Java 卡运行时环境支持多应用环
境。多个 applets 能够并存于同一张 Java 智能卡上,并且一个 applet 可建有多个实例。例如,
可建立一个钱包 applet 实例支持美元, 而建立另一个实例支持英镑。
3.8 包和Applet 命名约定
你所熟悉的 Java 平台中的包和程序是利用 Unicode 串和基于 Internet 域名的命名方案来
唯一标识的。然而,在 Java 卡平台中,每个 applet 实例是通过应用标识符(AID)来唯一标识
和选择的。另外,每个 Java 包也被赋予一个 AID 。当把包装载到卡片上的时候,便通过它们
的AID将其与卡片上的其它包链接起来。
ISO 7816 规定了用于唯一标识卡片的应用和卡片文件系统中某些类型域的APIs。一个 AID
是一个字节数组,可被解释为两个不同的部分,如图 3.6 所示。第一部分是一个 5 字节的值,
称为 RID (源标识符)。第二部分是一个可变长度的值,称为 PIX (专用标识符扩展)。 PIX 的长
度可从 0 到 11 字节。因此,一个 AID 总长可从 5 到 16 字节。
RID (5 bytes) PIX (0–11 bytes)
图 3.6 应用标识符 (AID)
ISO 控制给公司 的 RIDs 分配;每个公司有一个唯一的 RID。 公司自己管理AIDs中的
PIXs 的分配。本节只对 AIDs 进行简要地描述。关于全部细节,请参见 ISO 7816-5,AID 注册
分类 D 的格式。
在 Java 卡平台中,一个包的 AID 是通过该公司的 RID 和这个包的 PIX 的链接而构成的。
一个 applet 的 AID 是以和包 AID 类似的方法而构造的。它是该 applet 提供者的 RID 和该
applet 的 PIX 的链接。一个 applet 的 AID 一定不要用和任何包的 AID 或任何其它 applets 的
AID 相同的值。然而,由于一个 AID中的 RID 标识 applet 提供者,包 AID 及在该包中定义的
applets 的 AID(s) 必须具有相同的 RID。包 AID 和在该包中定义的每个 applet 的缺省 applet
AID 在 CAP 文件中指出。在生成 CAP 文件时,将它们提供给转换程序。
3.9 Applet 下载过程
Java 卡 applet 的开发和任何其它 Java 程序一样而开始。开发者编写一个或多个 Java 类
并用某 Java 编译器编译源代码,产生一个或多个 class 文件。图 3.7 演示了applet 的开发过程。
接着,在模拟环境中运行、测试,和调试该 applet。模拟器在 PC 或工作站上模拟 Java 卡
运行时环境。在模拟环境中,applet 于 Java 虚拟机上运行,并因此而执行该 applet 的 class 文
件。通过这种方法,模拟器能够利用许多 Java 开发工具(虚拟机、debugger, 和其它工具)并允许
开发者
图 3.7 Applet 的开发过程
测试 applet 的行为和快速观看 applet 的执行结果,而不用经历转换过程。在这一步中, applet 的
整个功能方面得以测试。然而,某些 Java 卡虚拟机运行时特性,例如 applet 防火墙以及对象的
临时与永久行为,则不能被检查。
而后,通过 Java 卡转换程序将构成一个Java包的 applets 的 class 文件被转换为一个 CAP
文件。Java 卡转换程序的输入不仅有被转换的 class 文件,还有一个或多个 export 文件。在转
换该 applet 包的时候,转换程序还为这个包产生一个 export 文件。 一个 CAP 文件或一个 export
文件代表一个 Java 包。如果一个 applet 由若干包组成,那么为每一个包建立一个 CAP 文件和
一个 export 文件。
在下一步中,将代表该 applet 的 CAP 文件(可能不止一个)装载到一个仿真环境中并在该
环境中进行测试。仿真器也在一台 PC 或工作站上模拟 Java 卡运行时环境。然而,仿真器是一
个更为复杂的测试工具。它包含一个 Java 卡虚拟机 的实现。Applet 在仿真器中的执行行为应和
运行于实际卡片中的行为是一样的。在这一开发阶段,不仅 applet 得以进一步测试, 而且该 applet
的运行时行为也得到测试。
大多数 Java 卡模拟器和仿真器都带有调试程序(debugger)。该调试程序允许开发者设置断
点或单步执行程序、观看在该模拟或仿真的 Java 卡运行时环境中的 applet 修改后的执行状态。
最后,当 applet 被测试后并准备好被下载到实际的卡片中的时候,该 applet(由一个或若干
的 CAP 文件代表)便被装载和安装到 Java 智能卡中。
3.10 Applet 安装
在制造 Java 智能卡的时候, 该智能卡的专用系统及其运行时环境(包括本地(native)方
法、Java 卡虚拟机、API 类,以及库)都被烧到 ROM 中。这个将一些固定的成分写到芯片的
不易变的存储器的过程称为掩模(masking)。掩模技术是智能卡厂商的专用工艺技术,本书不再
进一步讨论。
3.10.1 ROM Applets
在卡片制造过程中,Java 卡 applet 类可以和 JCRE 及其它系统成分一起掩模到 ROM 中。
在 JCRE 初始化期间或以后某一时刻,由 JCRE 将 Applet 实例实例化到 EEPROM 中。这样的
一些 applets 称为 ROM applets。
ROM applets 是缺省的 applets ,由卡片发行者提供,随卡一起提交。由于 ROM applet 的
内容由发行商控制,Java 卡 工艺技术允许 ROM applets 声明本地(native)方法,这些方法的
实现是利用别的编程语言(例如 C 或汇编代码)写的。本地方法不受由卡片虚拟机强制的安全
检测。.
3.10.2 事前或事后发行 Applets
另外,在卡片制造之后,Java 卡 applet 的类和相关的类库也能够被下载或写到 Java 智能卡
的可变存储器(例如 EEPROM)中。这样的 applets 可进一步分类为事前发行或事后发行的
applets。事前和事后这两个词是根据 applets 是在卡片发行之前或之后下载的事实而确定的。事
前发行的 applets 按 ROM applets 相同的方式处置,二者都由发卡方控制。
和 ROM applets 或事前发行的 applets 不同,事后发行的 applets 不允许声明本地方法。原
因在于 JCRE 没有办法控制该 applet 的内容。允许被下载的 applets 包含本地代码会有损于
Java 卡的安全性。以下几节将集中于事后发行的 applet 的安装。通常,事前发行的 applets 是
利用和事后发行的applets相同的机制装载的,但是 Java 卡技术把决定权留给卡片发行者。
3.10.3 事后发行的 Applet 的安装
Applet 安装指的是将 applet 类装载到一个 CAP 文件中、将这些类和 Java 卡运行时环境的
执行状态相结合,以及建立一个 applet 实例,从而使该 applet 成为能被选择执行的状态的过程。
在 Java 卡平台上,装载和可安装的单位是一个 CAP 文件。一个 CAP 文件由构成一个 Java
包的类组成。一个最小的 applet 就是一个只具有一个从 javacard.framework.Applet 类继承的类
的包。一个具有很多类的更复杂的 applet 可被组织成一个或一组 Java 包。
为了装载一个 applet,卡外安装程序将 CAP 文件作为输入并将其转换为 APDU 命令序列,
该命令序列携带该 CAP 文件的内容。通过和卡外安装程序交换 APDU 命令,卡上安装程序把
该 CAP 文件的内容写到卡片的永久存储器中,并将该 CAP 文件中的类与驻留在卡片上的其它
类相链接。该安装程序还建立和初始化任何由 JCRE 内部用于支持 applet 的数据。如果该 applet
需要若干包运行,要把每个相应的 CAP 文件都装载到卡片上。
作为 applet 安装的最后一步,安装程序建立一个 applet 实例并将这个实例向 JCRE3
注册。
为了做到这一点,安装程序调用 install 方法:
public static void install(byte[] bArray, short offset, byte length);
install 方法是一个 applet 入口点方法,类似于一个 Java 应用中的 main 方法。一个 applet 必
须实现 install 方法。在 install 方法中,它调用 applet 的构造方法以建立和初始化 applet 实例。
install 方法的 bArray 参数提供关于 applet 初始化的安装参数。这些安装参数随 CAP 文件一起
发送给卡片。applet 开发者定义安装参数的内容和格式。
在 applet 被初始化并向 JCRE 注册之后, 它便可被选择运行。 JCRE 利用AID (应用标识符)
标识一个正在运行的 applet。applet 可利用在 CAP 文件中找到的缺省 AID,或者另选择一个不
同的 AID 向 JCRE 注册自己。可利用安装参数提供一个另外的 AID。
install 方法可被调用多次,以建立多个 applet 实例。每个 applet 实例都由一个唯一的AID
标识。在 Java 卡环境中,一个 applet 可在不知道如何装入它的类的情况下而编写和执行。在安
装过程中,一个 applet 的唯一责任就是实现 install 方法。
3.10.4.Applet 安装期间的错误恢复
安装过程是事务性的。在发生错误的情况下,例如程序性故障、运行范围超出存储器大小、
卡片拔出,或者其它错误,安装程序都要抛弃该 CAP 文件和在安装过程中它已经建立的任何
applet 并恢复空间和 JCRE 的以前状态。
3.10.5. 安装限制
读者应当知道 applet 安装是不同于运行时动态类装载的,后者是在台式机环境中的 Java虚
程。
因此,Java 卡 applet 安装有两个细节。第一,运行于卡片上的 applets 仅指已经存在于卡
片上的类,由于在 applet 代码正常执行期间没有办法下载类。
第二, 装载的次序必须保证: 每个被新装入的包只引用已经在卡上的包。 例如, 对于一个 applet
来说,javacard.framework 包必须在卡片中, 因为所有的 applet 类都必须从类
javacard.framework.Applet 扩展而来。 如果存在包 A 和包 B 循环引用情况, 安装过程将失败。