CLDC (Connected Limited Device Configuration,有限连接设备配置) 是为运行在资源非常有限的设备(例如
寻呼机或者
手机)上的
J2ME应用程序制订的架构。规范内容包括目标机器的特性、
虚拟机规范和基本的API等等。 有1.0和1.1两个版本。
发展
CLDC是由包括
Nokia,
Motorola和Siemens在内的18 家全球知名公司共同协
商完成的。
CLDC 的核心是
虚拟机和核心
类库。虚拟机运行在目标
操作系统之上,对下层的硬件提供必要的兼容和支持;核心类库提供操作系统所需的最小的
软件需求。
2000年5月,
Java Community Process(
JCP)公布了CLDC1.0规范(即JSR30)。CLDC是
J2ME核心配置中的一个,可以支持一个或多个profile。其目标主要面向小型的、网络连接速度慢、能源有限(主要是电池供电)且资源有限的设备,如手机、机顶盒、PDA等。CLDC1.0的规范可以在
jcp的网站上下载。
目标
(1) 为小型的、资源受限的连接设备定义一个Java 平台标准
(2) 允许向上述设备动态的传递
Java 应用和内容
(3) 使Java 开发人员能够轻松的在这些设备上进行应用开发
整体需求
(1) 能运行在绝大多数的小型的、资源受限的连接设备上
(2) 用CLDC 为上述设备开发的应用尽可能的不使用设备的本地
系统软件(做到与平台、设备无关)
(3) 定义能应用在绝大多数上述设备上的最小子集的规范
(4) 保证在不同
类型上述设备之间代码级的可移植性和
互操作性1. CLDC 的硬件需求
由于CLDC 要面向尽可能多的设备,而这些设备所使用的硬件又各不相同。因此CLDC 规范中并没有指明需要某种硬件支持,只是对设备的最小内存进行了限制。CLDC 规范中要求硬件必须达到以下要求:
(1) 至少160KB 的固定内存以供
虚拟机和CLDC 核心类库使用。
(2) 至少32KB 的
动态内存以供虚拟机运行时使用(
堆栈等)。
这里所说的固定内存是指拥有
写保护,不会因关机而抹去的
ROM。对于具体的设备的具体实现,这些需求也可能有变化。这里所规定的160KB 是CLDC 规范中的要求,实际也可以是128KB 左右。
和硬件类似,CLDC 上运行的
软件也是多种多样的。例如,有些设备支持
多进程操作系统或者支持
文件系统;而有些功能极其有限的设备并不需要文件系统。对于这些不确定性,CLDC只定义了软件所必须的最小集合。CLDC 规范中要求
操作系统不需要支持
多进程或是分址空间寻址,也不用考虑运行时的协调和延迟;但是必须提供至少一个可控制的实体来运行
虚拟机。
功能范围
4.1 CLDC包含的功能在CLDC1.0版本中定义了以下功能:
(2)核心Java类库
(3)输入/输出
(4)对网络的支持
(5)对安全性的支持
(6)对国际化的支持
4.2 CLDC不包含的功能(1)对应用程序生命周期的管理
(2)用户界面
(3)事件处理
(4)高级应用程序
模式(这里指用户与应用程序的交互)
CLDC包含了一个基本的J2ME运行环境,其中包括
虚拟机和核心的java类库。作为专门针对于小型设备的配置,CLDC对J2SE类库进行了大量的简化,其类库只保留了java 规范中定义的最核心的3个包,即java.iojava.lang和
java.util,并重新定义了一个新的包javax.microedition。这里你可以通过前缀来区别:java.表示核心的
java包,
javax.表示标准
java扩展包。
这里要注意的是在CLDC中定义的javax.microedition包为javax.microedition. io,用来支持通用连接
框架(GCF,Generic connection framework)。CLDC中的包和所对应的功能如下所示:
(1) CLDC包
(2) 对应的功能
(1) java.io
(2) 标准的输入/输出功能,J2SE
java.io包的子集
(3) java.lang
(5) java.util
(6) 实用类
(7) javax.microedition. io
CLDC中的包和所对应的功能
javax.microedition中其他的包定义了CLDC中没有定义的功能,如对应用程序生命周期的管理、用户界面(UI)、事件处理
模式、永久性存储和用户与
应用程序的交互等。这些功能的定义是由
Profile (即
MIDP)来完成的。
4.4 CLDC核心类库与J2SE的主要区别
由于CLDC主要针对16位、32位主频在16MHz以上的处理器,设备内存只有512KB,甚至更少,而目前Windows平台下运行的
JVM需要的最小内存为16M。因此CLDC所使用的
虚拟机和核心类库与
J2SE的并不相同。
1.不支持浮点
数据类型(没有float和double)
因为很多使用CLDC的设备硬件都不支持
浮点运算,而且处理浮点运算需要较大的内存。因此在CLDC1.0中,并没有要求虚拟机支持浮点数据类型。
(9) dadd
(10) dmul
(11) fadd
(12) fmul
(13) i2d
(14) dalaod
(15) dneg
(16) faload
(17) fneg
(18) i2f
(19) dastore
(20) drem
(21) fastore
(22) frem
(23) l2d
(24) dcmpg
(25) dreturn
(26) fcmpg
(27) freturn
(28) l2f
(29) dcmpl
(30) dstore
(31) fcmpl
(32) fstore
(33) newarray(double)
(34) dconst_0
(35) dstore_x
(36) fconst_0
(37) fstore_x
(38) newarray(float)
(39) dconst_1
(40) dsub
(41) fconst_1
(42) fsub
(43)
(44) ddiv
(45) d2f
(46) fdiv
(47) f2f
(48)
(49) dload
(50) d2i
(51) fload
(52) f2i
(53)
(54) dload_x
(55) d2l
(56) fload_x
(57) f2l
(58)
CLDC不支持的浮点数据类型
对于CLDC的应用,Sun使用了和
J2SE相同的
编译器,这使得使用浮点数据的类及
对象在编译的时候可以正常通过。因此Sun引入了类审核机制来阻止未经定义的类调入
虚拟机。
2.不支持
JNI (the Java Native Interface )
CLDC不提供native code的支持,除了因为设备内存有限外,还出于安全性的考虑。因为CLDC中缺少完整的安全性模型,禁用了这些
J2SE的特性可以使潜在的安全风险降到最低。
3.不支持以及用户自定义的
Java级的类载入器(class loaders)
CLDC不允许用户自定义类载入器。按照CLDC规范的要求,类的载入是不能被覆盖、替换和修改的。和JNI类似,这些是出于安全方面的一些考虑。
4.不支持反射(reflection)
不支持
java.lang.reflect包以及java.lang.Class中和reflection有关的函数。其目的主要是节省内存占用。
5.不支持线程组(
thread groups)或守护线程(daemon threads)
CLDC提供了对线程的支持,也支持
多线程,但是
线程组和守护线程是不被允许的。每个线程都要生成独立??程的操作,则必须在应用程序的级别上自行实现多个Thread
对象的控制,如使用
Hashtable和Vector来存取多个Thread对象。
6.不支持类实例(class instance)的终结(finalization)
CLDC类库不包含java.lang.
Object.finalize()方法,因此类对象的终结是不支持的。对于应用CLDC的设备来说,对象终结相对于它所起的作用来说实现起来过于复杂,并不被需要。
7.不支持弱引用(weak references)
8.有限的错误处理(error handling)
在
J2SE中定义了大量的类用来描述各种错误和异常,而CLDC仅仅包含有限的几个J2SE的核心类库,因此大部分java.lang.Error的子类都未被支持,这包括
异步异常。这是因为在嵌入式系统中,应用程序并不期望获得设备的出错处理机制;定义和运行出错处理需要较大的
虚拟机的开销,而这些出错的代码信息对于连用户界面都没有的有限连接设备来说是没有用处的。
新特性
CLDC1.1即JSR139相对于1.0版本并没有本质上的变化。随着硬件水平的不断提高,CLDC1.1在
兼容性和可用性上作了一些改进,并增加了一些1.0版本没有的新特性:
1. 增加对浮点数据的支持
2. 核心类库中增加java.lang.Float类和java.lang.Double类
3. 部分支持弱参考(weak references)
4. Calendar、Date和TimeZone类被重新设计
6. 对错误处理有了更加明确的定义
7. 并增加了 NoClassDefFoundError 类
8. 对于Thread类
9. CLDC1.1允许为线程命名
10. 并通过getName() 方法得知线程的名字
11. 增加interrupt()方法
13. 对一些类库进行了小的修改
14. 以下的方法被添加或是修正: Boolean.TRUE and Boolean.FALSE Date.toString() Random.nextInt(int n) String.intern() String.equalsIgnoreCase()
16. 设备的最小内存被提高到160 至 192 KB
下面列出CLDC1.1增加的类和方法:
l 增加java.lang.Float和java.lang.Double类
l 增加以下和浮点数据相关的方法
java.lang.Integer.doubleValue()
java.lang.Integer.floatValue()
java.lang.Long.doubleValue()
java.lang.Long.floatValue()
java.lang.Math.abs(double a)
java.lang.Math.abs(float a)
java.lang.Math.max(double a, double b)
java.lang.Math.max(float a, float b)
java.lang.Math.min(double a, double b)
java.lang.Math.min(float a, float b)
java.lang.Math.ceil(double a)
java.lang.Math.floor(double a)
java.lang.Math.sin(double a)
java.lang.Math.cos(double a)
java.lang.Math.tan(double a)
java.lang.Math.sqrt(double a)
java.lang.Math.toDegrees(double angrad)
java.lang.Math.toRadians(double angrad)
java.lang.String.valueOf(double d)
java.lang.String.valueOf(float f)
java.lang.StringBuffer.append(double d)
java.lang.StringBuffer.append(float f)
java.lang.StringBuffer.insert(int offset, double d)
java.lang.StringBuffer.insert(int offset, float f)
java.io.DataInput.readDouble()
java.io.DataInput.readFloat()
java.io.DataInputStream.readDouble()
java.io.DataInputStream.readFloat()
java.io.DataOutput.writeDouble(double v)
java.io.DataOutput.writeFloat(float v)
java.io.DataOutputStream.writeDouble(double v)
java.io.DataOutputStream.writeFloat(float f)
java.io.PrintStream.print(double d)
java.io.PrintStream.print(float f)
java.io.PrintStream.println(double d)
java.io.PrintStream.println(float f)
java.util.Random.nextDouble()
java.util.Random.nextFloat()
l 增加浮点计算常量е和圆周率π:
java.lang.Math.E
java.lang.Math.PI
l 增加弱参考类java.lang.ref.Reference和java.lang.ref.WeakReference。
l 新增错误类NoClassDefFoundError。
Thread.getName()
Thread.interrupt()
Thread(Runnable Target, String name)
Thread(String name)
l 新增的一些常数及方法:
java.lang.Boolean.TRUE and java.lang.Boolean.FALSE
java.lang.String.intern()
java.lang.String.equalsIgnoreCase()
java.util.Date.toString()
java.util.Random.nextInt(int n)
要查看CLDC1.1更详细的变化可以去Sun的网站下载CLDC1.1的规范
安全机制
5.1 CLDC的安全级别
在CLDC中,
虚拟机不允许用户安装程序,因此安全特性和
J2SE比要少很多。CLDC规范中主要定义了以下3个级别的安全机制:
1,底层安全机制(low-level security)
底层安全就是通常说的虚拟机的安全,是虚拟机运行在CLDC设备上的最关键的安全机制。它要求运行在虚拟机上的应用程序必须遵循
Java语言的标准语法,且能够检查出并组织恶意代码(类)以各种方式对设备进行破坏。对于标准的Java虚拟机的实现,虚拟机使用类审核的方式来保证虚拟机安全。类审核机制能够确保类
文件中的
字节码以及其他
对象不包含非法指令,不会以非法的顺序被执行,也不会访问
虚拟机以外的非法内存地址或是地址段。
在CLDC中,类的审核机制不同于
J2SE,它增加了预审核(pre-verification)机制。2.3.1节将对CLDC的预审核机制做详细的说明。
2,应用级别安全机制(application-level security)
仅用类审核机制来保证
Java平台的安全运行是不够的。因为它仅仅能够确保应用程序的代码是可用的,还有很多潜在的安全威胁没有被涉及到,如对
文件系统、打印设备、红外、本地类库以及网络等安全管理。在应用级别安全机制中,CLDC规定,
Java应用程序只能访问系统类库、
系统资源、额外的设备元件(如
即插即用的设备等)和Java运行环境。
具体的实现是:应用程序运行在一个封闭的
沙箱(
sandbox)环境中以得到保护。在沙箱中,只有系统已定义的配置(configuration)、简表(profile)、
可选包以及设备支持的一些类可以被应用程序访问。任何没有预先定义类库和资源都不允许访问,以防程序中的恶意代码对沙箱外的资源(如
操作系统、硬盘等)非法访问或者破坏。
沙箱的需求主要有:
l 应用程序的下载、安装和管理等操作都不能修改、覆盖或着绕过类
虚拟机实现的标准的加载机制。
l 只有预先定义好的,封闭的Java API和类可以被应用程序调用。这包括配置、简表、
可选包以及该应用自定义的类。
l 任何没有被CLDC定义的native code都不允许调用。这意味着应用程序不能下载一个新的含有native code的类库并使用。
l CLDC规范额外规定了系统类和应用程序类的命名规则。也就是说,为了满足上面说的
沙箱的要求,所有java.*和java.microedition.*都属于系统类,不能被覆盖,修改;也不能任意增减。应用程序类不能使用上述包名来实现自己的类。
l 而且,除了调用系统类之外,应用程序只能调用自身JAR包中的类。这样保证了应用程序不能从其他的应用程序中“偷”数据(或类的实现)来达到自身的目的。
注:在最新的JSR246(Device Management)中,通过设备管理
框架(Device Management Framework),满足一定条件的应用程序有可能访问其他应用程序的数据,但是对绝大多数应用程序来说,别人的数据仍然是不可以访问的。(想用楷体,但是机器上没有除
宋体以外的其他字体……哭)
3,端对端的安全机制(end-to-end security)
端对端的安全机制主要指在数据传输时的安全,如
数字签名、加密等机制。考虑到网络不是CLDC设备必须支持的功能,这方面的定义是由上层相应的简表来完成的,如
MIDP;CLDC规范中并没有详细的规定。
J2SE提供了
字节码的审核机制用于检查类
文件的完整性。该审核机制是在编译时进行的,其目的是确保类文件中不包含可能破坏系统安全的或是违反了
Java语言规范的恶意代码。其内容主要包括:
(2)在构造
对象时,其
构造函数必须在该对象被使用前调用
(3)每个对象的
构造方法都必须调用父类的构造方法(要求最先调用
java.lang.Object的构造方法)
(4)本地变量、实例和
静态成员在声明时指明的对象
类型必须和实际赋值的对象类型一致。例如,给一个声明成String类型的变量赋予Integer类型的值是不被允许的。
类的审核机制仅仅针对于外来的类
文件(比如从网络上下载的),而对本地文件系统中的类的加载是不用审核的。
CLDC和
J2SE一样,也要求
虚拟机能够辨别并拒绝非法的类文件。但由于J2SE中定义的标准类审核过程对于应用CLDC的小内存消耗的小型设备来说是不现实的,因此CLDC专门定义了其特有的预审核机制。
在CLDC的预审核机制中,要下载的
Java类
文件的每一个方法都包含了一个
堆栈映射属性,这个属性是CLDC独有的,J2SE规范中没有定义。堆栈映射的属性会通过虚拟机的预审核器添加到标准的类文件中,该预审核器会分析类中的每一个方法。堆栈映射属性通常会增加约5%的类的大小。
如图所示,当程序的
源程序被编译后,必须被预审核器预审核,然后才能生成可以被下载到目标设备上运行的类
文件。把一部分的审核任务放在预审核器中完成,可以使与CLDC兼容的
虚拟机审核
Java类文件时速度更快,并且只需要很少的虚拟机代码和
动态内存,而它们的安全级别相同。因此,在CLDC/
MIDP环境下开发程序,其程序经过编译后,必须经过预审核后才能运行。
特别需要说明的是:
1. 经过预审核器审核过的Java类文件不需要修改就可以直接运行在
J2SE和
J2EE环境上,这使得移植和相互调用变得非常简单。
2. 运行时的审核机制CLDC把它交给了设备自己去实现。设备可以根据自身的需要在加载类或是安装应用程序的过程中执行。在运行时,
虚拟机迅速地对
字节码进行线性扫描,将每个有效的指令与合适的
堆栈映射项相匹配。运行时的审核过程是建立在预审核机制之上的,所以比预审核还要快,占用的
动态内存更少。
CLDC要求所有第三方开发的支持CLDC的
Java应用程序在
公开发布时都要使用JAR包的格式,而且JAR包内的类必须是经过了预审核器审核之后的。同样的,CLDC要求所有实现CLDC的虚拟机也必须能够识别和调用JAR包中的文件。
类库
CLDC标准为了能够涵盖尽可能多的设备,其类库只包含了最小的
Java平台特性和API。面对严格的内存限制和当前各种各样的小型设备,CLDC不可能覆盖全部的这些设备。因此在CLDC的规范中,不可避免的会造成对某些设备要求过高或是对另一些设备要求又太低的现象。
为了确保与其他Java平台的兼容性,绝大多数的CLDC类库是从
J2SE和
J2EE中继承的,是J2SE和J2EE的子集。由于目标设备的特殊性,CLDC类库在安全、输入/输出、用户界面、网络和
存储管理等方面没有全部使用J2SE的实现;其中的部分类库CLDC进行了重写,如网络连接。
如4.3中所介绍的,CLDC的类库可以分为两种:一种是从J2SE标准类库中继承的;另一种是专门为CLDC设计的(这部分类也可以被映射到J2SE中)。
对于第一种CLDC类库,包括了J2SE的3个最核心的包
java.io、java.lang和
java.util。而且这3个包和J2SE相比,也只是
J2SE相应包的一个很小的子集。例如java.util的类与接口由J2SE中的53个减少到10个。
对于后一种CLDC类库,只有描述标准连接
框架的javax.microedition. io包,和
MIDP中定义的包一起放于javax.microedition包中。
6.1 java.lang包
java.lang包包含了
Java语言API的核心部分继承下来的类,但是CLDC只继承了J2SE中一半的类,而且一些类中的接口并没有完全实现。这主要表现在:
(1)绝大部分的
虚拟机不支持错误类和部分异常类被去掉了。
(2)不支持Float和Double
数据类型及其相应的类
(3)ClassLoader、SecurityManager等CLDC规范上没有说明必须支持的类也不在此包中。
下表给出了CLDC 的
java.lang包中的类及类的继承关系。
Object类中需要注意的有以下两点:
2. 没有接口类java.lang.Cloneable,所有CLDC
虚拟机的
对象都没有默认的
clone()方法。
数据类:
在前面已经提到过多次,CLDC不支持浮点
数据类型,核心库中的java.lang.Floart类和java.lang.Double类以及其他类中与浮点数据相关的方法均不予支持。CLDC支持的数据类型有:
Boolean、Byte、Char、Integer、Long、
Short和String。
需要注意的是:
1. java.lang.Number不在核心库中,java.lang.Byte等基本数据类直接从
java.lang.Object类继承。
2.接口类java.lang.Comparable没有出现在CLDC规范中,所以
数据对象之间不能像
J2SE那样直接调用
compareTo()方法比较。
3.
String类与J2SE相比变化较大,其中去掉了compareToIgnoreCase()、copyValueOf()、equalsIgnoreCase()、
split()、match()和intern()等方法;其余部分方法进行了缩减。
4. java.lang.Math类相对J2SE功能要小很多,只提供了和int、long有关的三组操作。
forName()方法和newInstance()方法仍然可以用,用来获得未知的
class对象。getResourceAsStream(String name)方法可以找到指定名字的资源,并以
InputStream的形式获得。该方法常用于读取本地MIDlet JAR包中图片或者文本
文件或是某个
Java包。参数——name可以是
绝对路径(以“/”开头,如/com/sun/MIDlet1/resources/pic.png),也可以是相对于当前
MIDlet目录下的
相对路径(如resources/pic.png)。
System类和Runtime类:
Runtime类和System类实现设备底层的操作,这些操作通常会涉及底层。考虑到底层相关的属性和
虚拟机性能等约束的原因,这两个类都仅仅包含了
J2SE有限的几个方法。
1. 在CLDC的简表
MIDP中定义一些J2SE中没有的系统属性(见表2.5)。通过
getPropertysetProperty()或setProperties()方法定义自己的属性。原有的通过
JNI连接native code的方法由于JNI的不支持也都被省掉了。其中,如果支持多个简表,中间用空格区分。
(59) 名称
(60) 含义
(61) 值
(62) microedition.platform
(63) 主机平台或设备的名称
(64) 默认值为null
(65) microedition.encoding
(66) 默认编码格式
(67) 默认值为“ISO8859_1”
(68) microedition.configuration
(69) 所支持的配置版本
(70) 默认值为“CLDC-1.0”
(71) microedition.profiles
(72) 所支持的简表名称
(73) 默认值为null
系统属性列表
2. J2SE中最常用的常量err和out仍然被System类保留了,但是常量in被删掉了。所以CLDC中没有标准的输入
数据对象了。
3. 还要注意的是停止
虚拟机运行的exit()方法。CLDC虽然允许
MIDlet(应用程序)直接调用并执行该方法,但是MIDlet会收到SecurityException的异常。
4. 由于设备的内存限制,J2ME中gc()的使用率比
J2SE高出很多,但是其本质和J2SE并没有区别,垃圾收集的工作全权由系统负责。另外在J2ME中使用gc()时要找准时机。
Thread类和Throwable类:
CLDC要求
虚拟机必须支持
多线程,即使底层平台并不支持。J2SE中对多线程的定义——Tread类、关键字
synchronized、
对象的wait()、
notify()和notifyAll()等方法都纳入了CLDC规范。然而,CLDC并不支持
线程组,也没有提供TreadGroup类。
1. 线程不能自己取名,即getName()和setName()方法在CLDC中不予提供。
2. 删除了
resume()、suspend()和stop()方法。这些方法在J2SE中已经是不在推荐使用的了(depredated)。
3. 线程
对象没有destory()、interrupt()和isInterrupted()方法。因此,CLDC的线程必须由
程序员自己控制结束(通常用
boolean变量+循环来控制),如:
Public void run() {
//the actions in the thread
}
}
4. dumpStack()方法被去掉了,类似的操作会
抛出异常。
java.lang包中定义的,而错误类仅仅3个。这些错误类和异常类都和
J2SE中的相同。特别需要注意的是Throwable类中的printStack()方法。该方法的输出格式由
虚拟机的实现自行规定;特别是在Sun的实现
KVM中,该方法仅仅会把异常的名字打印出来。
CLDC的java.util包主要包括了集合类和时间、日期的相关的12个类。其中的10个类是从J2SE中继承来的;
Timer和TimerTask类是
MIDP增加的类。
集合类:
CLDC规范中包含了4个集合类:
Hashtable、Stack、Vector和
Enumeration。和
J2SE相比,它们的功能被大大削减了,这点从继承关系上就可以看出:J2SE中的集合
框架被取消了,它们都直接从
java.lang.Object类直接继承。
Date类:
CLDC的Date类比J2SE要简单的多。Deprecated
构造函数和方法都被除去了;多个Date
对象的比较方法只能用equals()来进行。因此,我们不能直接通过Date对象获得时间(日期)的一部分,如年、月、日等。这些功能仅在
Calendar类中有定义。
TimeZone类:
CLDC规范规定设备只需要支持其默认的GMT时区。在KVM的实现中,支持GMT和UTC两种时区表示。
Calendar类:
Calendar类是
抽象类,没有直接的
构造方法,要构造一个默认的Calendar
对象必须调用
静态方法getInstance()。下面列出了Calendar对象不同的构造方法:
Calendar cal = Calendar.getInstance();
TimeZone timezone = new TimeZone();
Calendar cal = Calendar.getInstance(timezone);
Date date = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
在Date类的介绍中提到过,Date类中不能提取时间的一部分,而和
Calendar类一起使用就可以很容易的完成Date
对象的分解和加减等的运算。
Calendar类不能以字符串的形式返回年月日,因为CLDC没有包含
java.text包。在KVM的实现中,只能通过
toString()方法获得形如Sat, 9 Apr 2005 12:00:00 UTC的字符串。不同的
虚拟机的实现可能会返回不同格式的字符串。
MIDP通过Timer和TimerTask类提供了一种实现简单的多任务调度执行的方法,调度由一个专门的后台线程完成。其中,TimerTask 是用户定义的需要被调度的所有任务的
抽象基类。Timer 类在任务执行的时候负责创建和调度执行线程。这些调度由Timer类的schedule()和scheduleAtFixedRate()方法来完成,而run() 方法用来执行各个任务。此外每个 正在执行的任务必须能够尽快的终止,因为每个 Timer
对象在同一时间只能执行一个任务。
schedule()和scheduleAtFixedRate()方法都可以通过指定任务的开始时间、延迟时间或者任务的持续时间来调度任务。两者的区别在于,当某个任务因为某种原因出现一段时间的延迟后,之后所有由schedule()方法调度的任务都会顺延;而之后所有由scheduleAtFixedRate()方法调度的任务会自动根据一个固定的频率来调整。也就是说,在相同的一段时间内,如果用schedule()方法执行10次的任务,用scheduleAtFixedRate()方法调度可能会执行9次或是11次。
另外,TimerTask类提供了cancel()方法用于在任务执行的过程当中强行终止任务,该方法是从
Runnable接口类继承来的。一旦终止了该任务,那么它将退出任务调度。在任何时间调用cancel()方法都是有效的,即使该任务还一次都没有执行过。
6.3
java.io包 CLDC的java.io包是
J2SE的子集,只提供了相当有限的8位输入/输出功能。而且,一些
抽象类,像FilerInputStream等,也被省掉了,原先从这些抽象类继承的类直接从它们的父类
InputStream和
OutputStream继承。这里只表2.5给出了CLDC中java.io包中的类及类的继承关系。
对于CLDC,
InputStream和
OutputStream类是读写数据的唯一的途径。无论是本地
文件或是网络连接的读写都要通过这两个类来完成。一个典型的例子就是:
MIDlet提供了本地存储方式——RecordStore,它以
字节数组的形式存储内容。MIDlet需要把要存的内容转换成ByteArrayInputStream或是
DataInputStream对象格式来储存。同样的,调用在javax.microedition.rms中操作RecordStore的API所返回的也是ByteArrayOutputStream或是DataOutputStream对象。
由于CLDC不支持浮点数据,因此DataInput和DataOutput接口类只提供了对
boolean、char、int、long和
short型数据的读写操作。
DataInputStream、DataOutputStream类在
J2SE中是从FilerInputStream和FilerOutputStream继承来的。CLDC中FilerInputStream和FilerOutputStream被省掉了,所以
DataInputStream和DataOutputStream直接成为了
InputStream和
OutputStream的子类。DataInputStream类不能直接构造,要通过其他方法获得。例如,通过javax.microedition. io.Connector中的openDataInputStream方法,这是CLDC通用连接
框架(GCF)中从网络获取数据流的最长用的方法。而DataOutputStream类可以直接构造,也可以通过如javax.microedition. io.Connector中的openDataOutputStream等方法获得。
Reader和Writer类从
java.lang.Object继承,基本上与
J2SE区别不大。它们的作用是提供有限的国际化支持。J2SE中这是通过Reader和Writer
对象实现的,而CLDC中使用了
InputStream和
OutputStream来完成同样的功能。
InputStreamReader类用于把8位的输入数据流转化成
unicode码。然而,在CLDC规范中仅要求设备支持自身默认的编码格式,其他的编码格式可以有选择的支持。CLDC也不提供可以在运行时把应用程序的编码自动转成设备默认编码格式的功能。系统支持的编码格式可以从系统属性microedition.encoding中获得。如果系统不支持指定的编码,会抛出UnsupportedEncodingException异常。需mark()和reset()方法;而
J2SE中的getEncoding()方法被去掉了。
和InputStreamReader类似,OutputStreamWriter类中也去掉了J2SE中的getEncoding()方法。
PrintStream类直接从
OutputStream类继承,不支持浮点数据的打印。同时需要注意的是,print()和println()不会抛IOException,需要用checkErro()方法查看错误状态。
CLDC的
java.io包提供的IOException及其4个子类都和J2SE相同,这里就不再说明了。
6.4 javax.microedition. io包
javax.microedtion.io包定义了GCF中的类和接口,其中最关键的是Connector类和
Connection接口。Connector类中定义了
静态方法生成特定
类型的Connection,利用这个Connection可以访问网络和各种其他设备。