2.2.1 java.lang包
CLDC的java.lang包只有J2SE包的一半的类,而且还有一些类没有完全实现。下面就主要的部分作一下讲解。
2.2.1.1 对象类
CLDC的java.lang.Object类没有finalize()方法,因为CLDC虚拟机没有实现结束。而且,clone()方法已经被从java.lang.Cloneable接口中移除。所以,在CLDC虚拟机中没有方法来复制对象
2.2.1.2 数字相关的类
就如前面所述,浮点运算没有被CLDC的虚拟机支持,所以J2SE中的java.lang.Float和java.lang.Double类不在核心库集中。其他的数字类(Byte,Integer,Long和Short)都被提供了,但是J2SE基础类java.lang.Number没有包含。所以,这些数字类是继承于java.lang.Object 而不是Number类。其他值得注意的地方就是java.lang.Comparable接口没有包含在CLDC中,所以CLDC数字就不能像J2SE中一样进行比较
2.2.1.3 反射特性
反射机制的排除意味着java.lang.Class中的与这个相关的特性都会被移除。然而,使用forname()和newInstance()方法来对在编译时间不明确类型的类进行有限的操作是可能的。
2.2.1.4 系统属性
CLDC概要定义了一个非常小的系统属性集合。需要提供的实现如表2-2所示。
属性名称 |
意义 |
例子 |
microedition.configuration |
平台支持的J2ME的名称和版本号码 |
CLDC-1.0 |
microedition.encoding |
设备支持的缺省字符编码。设备没有被要求提供额外的编码,但是销售商可以这么做。然而,没有方法来发现哪一种编码是可用的 |
ISO8859_1 |
microedition.platform |
平台或者设备的名称。缺省的KVM实现中这个值为Null |
J2ME |
microedition.profiles |
设备提供的J2ME概要,以空格分开。因为KVM没有提供任何概要,所以这个属性的值为Null |
MIDP-1.0 |
特定属性的值可以通过java.lang.System类中的getProperty()方法来获得:
String configuration = System.getProperty(“microedition.configuraion”);
因为CLDC的java.util包没有包含J2SE的属性类,System类没有包含getProperties()方法,所以不可能得到这些属性。销售商可以自己加入面向属性的实现,但是应用代码来定义这些实现是不可能的,因为这里没有setProperty()方法。那些支持多种J2ME概要的设备必须在microedition.profiles属性包含那些概要和定义自己属性的概要
2.2.1.5 系统和运行类
J2SE中的System和Runtime类包含了一些进行低层次操作的方法集合。这些操作通常解决host平台的问题,例如在java应用程序中执行本地语言的可知性文件。因为这些操作是平台独立的,加上虚拟机的限制,这些类的许多特性都被移出了,包含如下:
1. 使用getProperties(),setProperity(),setProperties()这些方法来获取或者设置系统特性
2. 允许标准I/O/错误流改变原和目的值的方法
3. 提供本地代码库的访问的方法,因为不支持JNI
4. 反射和改变主动的SecurityManager的能力
2.2.1.6 线程
CLDC虚拟机被要求提供多线程编程环境,即使下面的平台没有。J2SE中使用的java支持多线程的编程接口——关键字synchronized,方法体objectwait(),notify()和notifyAll()和Thread类——都包含在CLDC规范中。然而,CLDC没有提供线程组和ThreadGroup类。J2SE中的一些线程特性也被移出了:
1. 所有与ThreadGroup相关的方法和构造器都移除了
2. 线程没有应用程序可设置的名称,所以setName()和getName()就不需要了
3. resume(),suspend()和stop()方法被移除了。这些方法在许多情况下J2SE中是不使用的,因为它们在锁多线程环境中有内在的不安全的因素
4. destroy(),interrupt()和isInterrupted()方法不存在。所以,唯一一种终止线程的方法就是通过一个线程经常检查的变量来通知。可以使用构造器这样做:
public void run() {
while (!requestedToStop){
// Do whatever is required
}
}
5. dumpStack()方法也被移除了。唯一一种因调试目的(而不是在调试器下运行代码)获取堆内容的方法就是抛出异常,就如下一节所述。
2.2.1.7 异常和错误
就如在2.1.1.2节所述,CLDC包含了J2SE中定义的大部分异常,但是大多数的错误的类被移除了,只留下了以下的类:
1. java.lang.Error
2. java.lang.OutofMemoryError
3. java.lang.VirtualMachineError
Throwable类的方法printStackTrace()是CLDC规范的部分(尽管致力于栈追踪的超载版本不是)。然而,这个方法的输出格式是独立实现的;更重要的是,在KVM的参考实现中,这个方法仅仅打印出异常的名称。为了得到栈的执行轨迹,重新使用非零的标记PRINT_BACKTRACE来编译内核或者使用虚拟机的调试版本(在windows平台的j2me_cldc\bin\win32\debug,这个版本的虚拟机就是以那种方式编译的)
就如前面的一节所述,Thread的方法dumpStack()是不可用的,所以如下通常的J2SE代码在CLDC中是无法编译通过的:
Tread.currentThread().dumpStack();
不幸的是,试图以异常的方式来解决这种问题也是失败的:
new Exception().printStackTrace();
这在J2SE中是可以的,但是由于CLDC没有要求在虚拟机在异常创建的时候填充栈轨迹,所以在CLDC中是失败的.仅当异常真的抛出的时候,KVM填充栈轨迹,所以唯一的方法来得到栈轨迹就是使用KVM的调试版本并且包含如下的代码:
try{
throw new Exception();
}catch (Exception ex) {
ex.printStackTrace();
}
当然,这个技术在生产型的CLDC平台上是不可用的,如没有把调试功能编译进去的蜂窝电话。幸运的是,大多数的问题都可以在一个模拟的环境中诊断出来,在这个环境中使用的虚拟机的调试版本。