日期:2014-05-20  浏览次数:20695 次

一个J2ME类导致wtk模拟器异常退出问题
前几天刚发现一个自我感觉比较怪异的问题,今天又碰到一个问题。

快下班的时候经理走到我的工位边上,扫了一下我的屏幕(当时我正在为了周末不加班而努力coding),然后很镇定地对我问我:你这个问题快完了吧? 我赶紧回答:是啊,马上了。(搞定了就能下班了哇,心中暗喜,以为有什么好事) 。 “那好吧,再给你一个问题,你去把这个xx问题解决一下,中间省去若干xx问题的描述,哦,对了,这个问题尽快解决啊,今天弄完,周末就不用加班了”。  我顿时感觉被xx了一下,故作清醒之后,不得不应声:哦。行吧。没问题,我尽快解决。 于是我看着经理离去的背影,怀着xx的心情来解决这个问题。
幸好,老天还算有眼,让我能过一个好点得周末,跟了快两个小时的bug,锁定了问题代码,并且稀里糊涂得解决了。

一些过程和结果是这样的:

xx问题是这个程序不能在一些手机和wtk模拟器上工作。在手机上不能跟bug,因为根本打印不出来日志。程序运行在模拟器上时,会抛出一个系统错误(windows错误对话框那种弹出来),告知我zayit.exe发生错误,然后模拟器崩溃退出。错误画面:

查看错误的其它信息:


我启动debugger进行调试,一步一步确定问题位置,最后发现,问题出在下面一段代码上(List 1):

public class Conversation{
  private String mId = "";

  public Conversation(){
     synchronized(mId){
      mId = String.valueOf(System.currentMilliSenconds());
   } 

try{
   Thread.sleep(50); //线程休眠50,是防止有些手机忽略了很短得System.currentMilliSenconds()间隔,导致mId重复,因为可能会在很短时间内创建多个这个类的实例,且要保证mId唯一
  }
  catch(InterruptException e)
  {
      // do something
  }
 }
}


发现问题在这里之后,我尝试修改这段代码。我将构造器改造成这样(List 2):

public Conversation(){
      mId = String.valueOf(System.currentMilliSenconds());

然后编译运行,yes, 在wtk模拟器上能工作了。但是我仍旧不知道为什么。
于是我又对代码进行了修改,这次得代码跟List 1中的代码基本是一致的,只修改了一下部分(List 3)

private String mId = new String();


然后编译运行,依然可以在模拟器上运行,可是我还是不知道为什么。

并且修改之后,在之前那些不能运行的手机上也能运行了。另外一点是,原始的代码在KEmulator上运行正常,看来KE的兼容性还真很好,不过做兼容的程序兼容性太好也不见得是啥好事啊

后来仔细考虑了一下,这个synchronize块的确是错误的,是不应该有的,因为即使同时创建多个对象而导致mId产生竞争,那就让竞争着去吧,而不是导致抛出系统级的错误并且模拟器异常退出。所以有点怀疑是String类内部引用分配导致这个问题。

不知道大家有什么看法?
1 楼 linkerlin 2010-08-19  
mId++;
Thread.sleep(1);
mId++;
Thread.sleep(1);
即可。