设备兼容性
java老鸟们大多应该对java的所谓写一次到处运行留下了深刻的印象,我们已经习惯了所谓按照某种规范开发,然后写一次,到处调试的的模式。好吧,非常不幸的是,kjava设备的差异性要远高于 j2ee中各种应用服务器和平台之间的差异,现在的规则可能会变成,写一次, 到处修改。搞不好工作量的三分之一都会花费在这个上面。
大的厂商,比如nokia和索爱, 会提供定制版本的模拟器以及相关文档,在定制版本模拟器上运行可以节约一部分工作量,虽然很遗憾的是,他们的速度通常不怎么样,小问题也比较多。 而其他一些厂商可能完全没有模拟器和文档说明,特别是wm上的第三方kvm实现,那就只能自求多福了。
你必须认识到
* 模拟器和真机永远是有差异的, 只有在真机上运行过才知道后果,尤其是运行速度,网络连接方面。
* 不同手机的kvm实现之间是有巨大差异的,规范对这种差异基本上不做控制,UI的实现尤甚。
作为企业应用开发的一个惯例在j2me上也适用,尽早的确定设备型号,并一直持续在这些型号上进行测试。不要到交付用户的时候再最后做兼容性测试。
内存管理
大部分手机都是严格的内存受限设备,可用内存通常在256k-2m之间。 好吧,老java程序员的怀旧时光又开始了,你会发现在hotspot vm出现之前的一些概念也同样对kvm有效,主要是关于内存回收部分的代码,你需要打破你臭美的代码风格,强制设置一些已经在j2se世界抛弃的东西。
* 对需要回收的资源,需要强制将变量设置为null, 这样gc会优先回收。所以对于个头稍微大点的变量,都记得找个地方设置为null。
这事情比较极端的做法是甚至你确定不需要某个资源了,给变量重新赋值之前也需要设置为null。比如
Boy boy = new Boy("good");
boy = null; //这样gc才会知道先回收good
boy = new Boy("bad");
* 必要的时候调用System.gc进行强制回收, 信不信由你,在很多机型上它确实很有效。在内存消耗比较大的操作之后,调用这个效果很明显。
顺便说一句的是,在j2se的hotspot 的实现里,这样做的结果往往是让系统呆住。
* 尽量不要一次使用大型数组,尽可能拆分成小数组操作。
尤其是对图像的操作,诸如旋转之类,很容易内存死光光。
以上这三条已经可以让你的代码具有典型的异教徒风格了。另外一些final,static,访问方法和实例变量的差别,确实有一些书籍介绍如何如何,但是据我阅读的某本书籍中的测试,这些都是跟机型和kvm实现相关的,没有绝对标准。
异常处理
j2me的异常处理和j2se迥然不同。 一方面是因为设备通常没有什么控制台和文件输出的概念,约束你随意的打堆栈, 另外一方面,midp中的异常类的规范并不要求异常附带堆栈信息,只要求异常的堆栈包含类名而已。 这2条让异常很难准确定位。
少许幸运的是,一般模拟器都有debug的模式,这种模式一般有附带不完整的异常堆栈信息,这也是你可以在pc上开发看到一些异常堆栈的原因。但是在手机上则看不到,除非你安装debug版本的kvm。即便是这种debug模式,也不会附带常在j2se中出现的文件和行列信息, 问题定位也要繁琐一些。即便如此,你也应该庆幸可以在模拟器上发现大部分问题。
最后归结于设备兼容性的问题, 初次在设备上运行时,发生各种runtimExcepiton的概率非常高,而一个类名很难让你准确定位问题,所以编程习惯必须有所改变。
我的做法是
* 尽可能的对方法中的参数和变量进行检查。 防止空指针和索引之类的异常出现。
在j2se中我们一般只强调对入口参数的检查,不会太强调对过程中变量值的检查。这样毕竟会增加代码量。
* 尽可能的对一些入口出,网络部分, ui部分这些和设备依赖比较高部分的代码还有一些关键代码做runtimeException的捕获,方便定位调试。
而在j2se中的开发中,根据Effective java的表述, 对runtimeException,我们应该视为编程性错误,应该不做处理,让其尽早的暴露。问题是在j2me的环境很难暴露准确位置,所以还是自力更生比较现实一点,这样好过你到时候满世界的去怀疑异常是从何处代码而出的。
* 尽可能多的做单元测试也是个好路子。 要比在手机上去找问题节约时间。
== 日志 ==
受限于设备的特性, j2me中没法直接把日志输出到控制台或者文件. 而j2me的调试困难度决定了一个合理有效的日志机制显然是必须的,而且应该在程序开发初始就必须认真考虑。
实现日志的方式大致有3种
1. c/s模式, 将日志发送回后台存储, 在jdj中有篇文章介绍这种模式,优点是查找问题非常方便,在后台看就好了,缺点当然是资源消耗问题,还有有些错误有可能发生在联网之前,或者联网处理中。
2. 将日志输出到 rms中, 事后通过程序查看,但是注意rms一般都有大小限制,从几十k到几百k不等
3. 将日志输出到一个屏幕对象, 可以是form也可以是canvas,需要的时候调出来看。也可以和2结合使用。
我选择了第三种方式,将日志输出到一个日志屏幕,日志屏幕附带了一个sms发送日志的功能,这样出了问题,可以方便让用户直接把日志信息以短信的方式发送给我定位,呵呵, 至于短信费用,哪不是我考虑的问题:)。
另外为了方便内存的跟踪, 在测试阶段,日志应该可以自动生成一些内存使用情况信息。
有一些第三方的log4j实现 比如 Jadabs Log4 J2ME,log4jMini, Microlog4j。 有兴趣也可以参考一下。