先交代下前提:xml文件为UTF-8
以前在php开发是碰到过类似的事情,不过当时通过记事本打开后删除文件头部的空格就行了。但是今天在javaEE开发中用jDom时,却不能解决,为了解决这个问题,所以现在才能睡,为了不忘记现在这里记录下然后睡觉。
现象:
SAXBuilder builder = new SAXBuilder();
Document doc = null;
Reader in = new StringReader(xmlPath);
在 doc = builder.build(in);时,抛出错误:
Caused by: org.xml.sax.SAXParseException: Content is not allowed in prolog.
原因:
XML文件使用utf-8编码,在文件开始处含有不可解释的字符,该字符串称为BOM。使用软件UltraEdit打开xml文件,转到十六进制编辑,可以发现开始处为FFEF,就是这个字符引起了异常。
解决方法:
可以使用UltraEdit把utf-8转为ascii(在写xml文件时,使用UltraEdit软件编辑,记事本或其他xml软件默认是使用utf-8保存,在UltraEdit软件配置中可以设置默认保存为ascii)。
以上是网上普遍解决方法,然而我尝试后依然没法解决,最后使用FileInputStream in = new FileInputStream(xmlPath);代替Reader类,程序正常运行。
可以参考:
http://happyhou.blog.sohu.com/84258111.html
引用:http://blog.chinaunix.net/u2/65478/showart_1929128.html
2009年6月11日 星期四
2009年5月19日 星期二
『转』如何看懂Java混淆后的反编译代码
转这篇文章 也不用说我想干什么了。。。
作者:dozb
一般情况下Java应用的开发者为了保护代码不被别人抄袭,在生成class文件的时候都java文件进行了混淆,这种class文件用反编译工具得到的结果很难看懂,并且不能进行编译。本文从研究的角度,浅析如何读懂这种反编译过来的文件。
例子一:赋值
反编译过来的代码如下:
Node node;
Node node1 = _$3.getChildNodes().item(0);
node1;
node1;
JVM INSTR swap ;
node;
getChildNodes();
0;
item();
getChildNodes();
0;
item();
getNodeValue();
String s;
s;
原始语句:
Node node;
Node node1 = currDocument.getChildNodes().item(0);
node = node1;
String s = node.getChildNodes().item(0).getChildNodes().item(0).getNodeValue();
注解:
JVM INSTR swap ; //赋值语句
练习:
String s1;
String s8 = node.getChildNodes().item(1).getChildNodes().item(0).getNodeValue();
s8;
s8;
JVM INSTR swap ;
s1;
10;
Integer.parseInt();
int i;
i;
例子二:不带参数创建对象
反编译过来的代码如下:
JVM INSTR new #244;
JVM INSTR dup ;
JVM INSTR swap ;
CrossTable();
CrossTable crosstable;
crosstable;
原始语句:
CrossTable crosstable = new CrossTable();
注解:
练习:
JVM INSTR new #246;
JVM INSTR dup ;
JVM INSTR swap ;
Database();
Object obj;
obj;
例子三:带参数创建对象
反编译过来的代码如下:
JVM INSTR new #262;
JVM INSTR dup ;
JVM INSTR swap ;
String.valueOf(s2);
StringBuffer();
s.substring(j, i);
append();
s6;
append();
toString();
s2;
原始语句:
s2 = (new StringBuffer(String.valueOf(s2))).append(s.substring(j, i)).append(s6).toString();
注解:
此语句实际上是:s2 += s.substring(j, i) + s6;
练习:
例子四:for循环
反编译过来的代码如下:
int k = 0;
goto _L4
_L8:
...
k++;
_L4:
if(k < as.length) goto _L8; else goto _L7
原始语句:
for(int k=0;k < as.length;k++)
{
...
}
注解:
例子五:while循环
反编译过来的代码如下:
String s1 = "";
goto _L1
_L3:
JVM INSTR new #262;
JVM INSTR dup ;
JVM INSTR swap ;
String.valueOf(s1);
StringBuffer();
_$2(resultset, s, l);
append();
toString();
s1;
_L1:
if(resultset.next()) goto _L3; else goto _L2
原始语句:
String s1 = "";
while(resultset.next())
{
s1 = s1 + resultSetToString(resultset, s, l);
}
原文:http://dozb.bokee.com/2774482.html
作者:dozb
一般情况下Java应用的开发者为了保护代码不被别人抄袭,在生成class文件的时候都java文件进行了混淆,这种class文件用反编译工具得到的结果很难看懂,并且不能进行编译。本文从研究的角度,浅析如何读懂这种反编译过来的文件。
例子一:赋值
反编译过来的代码如下:
Node node;
Node node1 = _$3.getChildNodes().item(0);
node1;
node1;
JVM INSTR swap ;
node;
getChildNodes();
0;
item();
getChildNodes();
0;
item();
getNodeValue();
String s;
s;
原始语句:
Node node;
Node node1 = currDocument.getChildNodes().item(0);
node = node1;
String s = node.getChildNodes().item(0).getChildNodes().item(0).getNodeValue();
注解:
JVM INSTR swap ; //赋值语句
练习:
String s1;
String s8 = node.getChildNodes().item(1).getChildNodes().item(0).getNodeValue();
s8;
s8;
JVM INSTR swap ;
s1;
10;
Integer.parseInt();
int i;
i;
例子二:不带参数创建对象
反编译过来的代码如下:
JVM INSTR new #244
JVM INSTR dup ;
JVM INSTR swap ;
CrossTable();
CrossTable crosstable;
crosstable;
原始语句:
CrossTable crosstable = new CrossTable();
注解:
练习:
JVM INSTR new #246
JVM INSTR dup ;
JVM INSTR swap ;
Database();
Object obj;
obj;
例子三:带参数创建对象
反编译过来的代码如下:
JVM INSTR new #262
JVM INSTR dup ;
JVM INSTR swap ;
String.valueOf(s2);
StringBuffer();
s.substring(j, i);
append();
s6;
append();
toString();
s2;
原始语句:
s2 = (new StringBuffer(String.valueOf(s2))).append(s.substring(j, i)).append(s6).toString();
注解:
此语句实际上是:s2 += s.substring(j, i) + s6;
练习:
例子四:for循环
反编译过来的代码如下:
int k = 0;
goto _L4
_L8:
...
k++;
_L4:
if(k < as.length) goto _L8; else goto _L7
原始语句:
for(int k=0;k < as.length;k++)
{
...
}
注解:
例子五:while循环
反编译过来的代码如下:
String s1 = "";
goto _L1
_L3:
JVM INSTR new #262
JVM INSTR dup ;
JVM INSTR swap ;
String.valueOf(s1);
StringBuffer();
_$2(resultset, s, l);
append();
toString();
s1;
_L1:
if(resultset.next()) goto _L3; else goto _L2
原始语句:
String s1 = "";
while(resultset.next())
{
s1 = s1 + resultSetToString(resultset, s, l);
}
原文:http://dozb.bokee.com/2774482.html
2009年5月17日 星期日
【转】多核危机:Scala vs Erlang
近来在博客上关于Scala与Erlang之间的争论越来越热。未来注定是多核的世界,问题在于如何去解决多核的危机。Scala和Erlang是两门渴望成为其解决方案的语言,但它们也有些许的不同。那么它们所采取的方式各有什么利弊呢?
引入问题
摩尔定律已经改变了。我们不再获得和以前一样的时钟频率增长,取而代之,我们得到了更多的(CPU)核心。今天,也许你的笔记本都已经是双核的了。
为了利用多核的特性,应用程序需要支持并发。如果你的客户买了一台八核的机器,要向他们解释清楚正常情况下应用程序只会用到12%的CPU能力将是一件费时费力的事,即便该机器是为该应用量身定制的。
在未来,情况可能变得更糟。你的顺序执行代码不仅不会跑得更快,甚至有可能实际上跑得更慢。其原因在于,你获得越多的核心,由于功耗和散热的影响,每个核心就会更慢。几年之后,英特尔就会给我们带来32核的CPU,按这种趋势,在我们不知不觉之中数千核的CPU就会出现。但每个核心都会比现在的核心慢很多。
并发代码
一个显见的解决途径就是编写(或重写)软件以支持并发。最常见的方式莫过于使用线程,但大多数开发者都认为基于线程的应用编写起来特别的困难。死锁,饿死以及竞争条件对大多数并发开发者来说都是太熟悉的概念了。Erlang和Scala都大大减轻了这种痛苦。
语言概览
Scala常被看作是下一个主要的JVM语言。它结合了面向对象编程的范式和函数式编程的范式,与Java相比有着更简洁的语法,它是静态类型的,有着跟Java一样或者有时候更快的运行速度。有太多的理由值得去认真探索一下Scala。
Erlang是一门为健壮性而生的语言,由于它的设计,它自然又是一门有着极好伸缩性的语言。它比Java历史更早,但却常被看作引领未来并发的语言。它是一门动态类型的函数式语言,有着一些非凡的系统正常运行时间的成功例子。
争论核心
那么Scala与Erlang争论的到底是什么呢?说到底,就是性能表现与伸缩能力,但这争论也包括了其它像风格,语言特性以及库支持等等。这场争论开始于Ted Neward有一次无心的给出了他对几种语言的看法,并称“[Erlang]在其自己解释器上运行事实上[是]很差的”。
Steve Vinoski与Ted于是展开了几轮争论,但这一讨论很快转移到了更多的博客上,争论的焦点也转变成了Scala与Erlang之间那些有趣的差异和共同点。我们将总结每个有意思的论点并给出每种语言的利弊,并表达对一些问题的各种不同看法。
可靠性
Steve Vinoski就Ted所发表的帖子进行了回应,给出了他对于“Erlang在其自己解释器上运行”的感受:
事实上,Erlang在其自己解释器上运行得,很好很强大;如若不然,不可能有如此好的可靠性,它将只是又一个面向并发的有趣但却无用的语言实验而已。
Steve谈到这个问题,就算一个语言本身可靠,它所依赖的基础也必须可靠才行。因为Erlang从骨子里就是为可靠性而设计的,从而支持并发,所以它不会受到一些并发性常见问题的影响,这主要是底层库包在并发环境下运行很好。
另一方面,Scala是站在JVM之上的,所以一个重要卖点在于可潜在地使用所有现成的Java代码。然而,大部分的Java代码并非专为并发而设计的,使用Scala代码时要将此考虑进去。
轻量级进程
要运行大规模并发应用,你需要大量的并行执行。这可以通过几种方式达到。使用线程是一种常见的方式,使用进程又是另一种。其区别之处在于,线程与其它线程之间共享内存,而进程是相互独立的。这意味着线程需要像互斥信号这样的锁机制,防止两个线程在同一时间对同一内存进行操作,但进程不会受此问题影响,相反是使用一些消息传递机制来跟其它的进程间通信。但进程在性能和内存方面的代价是昂贵的,这正是人们就算知道基于线程的并发是一种极复杂的编程模型也宁愿选择它的原因。
Steve Vinoski这样写到:
提供互不共享的轻量级进程架构将使得大规模并发能力变得十分容易,但这并不意味着一旦你设计好了,剩下的就只是编程的工作那么简单。
Erlang采取了这样的并发方式。一个Erlang进程是非常轻量化的,Erlang应用常常拥有成千上万的线程甚至更多。
Scala通过基于事件的Actor从另一方面达到了同样的效果。Yariv Sadan解释说:
Scala有两种类型的Actor:基于线程或是基于事件。基于线程的Actor在重量级的OS线程内部执行。它们从不相互阻塞,但每个VM上可伸缩的Actor不会多于几千个。基于事件的Actor是简单的对象。它们是十分轻量化的,并且,像Erlang进程一样,因此它们可以在一台现代的机器上数以百万计的产生。
Yariv解释到,尽管如此,这里面也还是有一些区别的:
与Erlang进程的区别之处在于,每个OS线程内部,基于事件的Actor是顺序执行的并且使用没有强占式调度算法。这使得一个基于事件的Actor可能在很长一段时间内阻塞其OS线程(甚至是无限的)。
不可变性
Erlang是一门函数式语言。这意味着其数据是不可变的,像Java的String一样,并且没有副作用带来的风险。对数据的任意操作会产生一个该数据新的修改后的版本,但原数据仍然不变。在谈到健壮性的时候,不可变性是其需要高度注意的一个因素,因为没有代码可以无意间修改其它代码依赖的数据,但从并发的观点来看,不可变性也是一个十分重要的特性。如果数据不可变,其被两个并行执行路径更改的风险就不存在,因为没有办法改变它且不需要保持同步,所以数据可以被拷贝到其它机器上。
因为Scala构建在JVM之上,结合了面向对象和函数式方法的特点,它不具备像纯函数式语言的不可变性的保证。然而,在Yariv日志的评论部分,Yariv和David Pollack就这两门语言之间的差别展开了一场有趣的讨论。David,Scala Web框架Lift的作者,给出了他对于不可变性的看法:
不可变性 —— Erlang强制了这一点,而且你几乎无法绕过它。但是,与强制一个单一类型相比,你可以用Scala神奇强大的类型系统的剩余部分去交换。我在进行Scala Actor编码时使用不可变数据,而让Scala的类型系统负责其它类型。
Yariv问到:
只发送不可变类型难道不是一个重大限制吗?这意味着,例如,你不能从Hibernate装载一个简单的bean并将它发送给其它Actor。
David回答到:
我曾基于Scala的Actor构建个多个生产系统。实际上对于不可变性问题并没有多少工作需要处理。你只需要将你的相关类(消息)定义为不可变的,其它的就不用管了。
类型系统
Erlang是动态类型的,而Scala是静态类型的并且相比Java有着更强的类型系统。然而,与Java相比最大的一个区别是Scala可以类型推断。这意味着你可以省掉大部分的类型注解,使得代码更加干净而编译器照样会做所有的检查。
关于动态与静态系统之间孰是孰非的争论看来永远也不会停止,但Erlang和Scala之间却有着显而易见的区别。
尾递归或是循环
Yariv又提到:
函数式编程与递归从来都是形影不离的。实际上离开了尾递归你很难写出有用的Erlang程序,那是因为Erlang没有循环——它对一切都使用递归(这在我看来是一件好事 :))。
这显然使得Erlang与Scala产生了很大差别。Scala提供了很多更传统的迭代,但David Pollack并没看出在这种环境下尾递归有什么优势:
尾递归——对基于事件的Actor来说根本不是什么问题。
如此说来,这仅仅有关你的偏爱和风格罢了。
热交换代码
由于Erlang是为可靠性而生的,热交换代码(运行时替换代码)是其内建的天性。
JVM对热交换代码有所支持。类可以被改变,但由于其静态的类型系统,其方法签名是不可改变的——只有其内容可以改变。虽然有第三方工具致力于此,也有框架(提倡以一种使运行时更方便交换类的编程风格书写代码),但就算运行在JVM上,如何进行交换仍是取决于你的Scala Actor是如何构建的。Jonas Bonér就此给出了一个详尽的例子。
总结
Scala和Erlang都是致力于解决多核危机的语言。它们来自不同的背景和年代,因此对待某些问题的方式也不尽相同,然而在许多方面它们的共识大于分歧,至少在并发性上如此。
Erlang已经有着数十年的历史,并且已经在许多关键的真实系统中证明了自己。其不足之处在于它有一点像一个孤岛,最近的多语言编程的趋势似乎对Erlang社区影响不大。
另一方面,Scala是同一类型应用的新生儿。一些真实应用即将诞生,并且一些公司将未来押在了上面。Scala相对Erlang的最大优势在于,它运行在JVM之上并且可以利用所有现成Java代码、框架和许多工具。话虽如此,这种强大的能力也要求了更大的责任,因为大部分Java代码不可能自动适应Scala的Actor模型。
对于主流语言无法帮开发者解决的压力越来越大的问题,两种语言都对提供了相似的解决途径。希望你在读完这篇争论总结之后,能更清楚哪种语言更适合你的特殊要求,并对其深入了解。
未来是多核的。Scala和Erlang将会越来越流行。
查看英文原文:The multicore crises: Scala vs. Erlang
原文:http://tech.sina.com.cn/s/2008-07-09/0952725490.shtml
引入问题
摩尔定律已经改变了。我们不再获得和以前一样的时钟频率增长,取而代之,我们得到了更多的(CPU)核心。今天,也许你的笔记本都已经是双核的了。
为了利用多核的特性,应用程序需要支持并发。如果你的客户买了一台八核的机器,要向他们解释清楚正常情况下应用程序只会用到12%的CPU能力将是一件费时费力的事,即便该机器是为该应用量身定制的。
在未来,情况可能变得更糟。你的顺序执行代码不仅不会跑得更快,甚至有可能实际上跑得更慢。其原因在于,你获得越多的核心,由于功耗和散热的影响,每个核心就会更慢。几年之后,英特尔就会给我们带来32核的CPU,按这种趋势,在我们不知不觉之中数千核的CPU就会出现。但每个核心都会比现在的核心慢很多。
并发代码
一个显见的解决途径就是编写(或重写)软件以支持并发。最常见的方式莫过于使用线程,但大多数开发者都认为基于线程的应用编写起来特别的困难。死锁,饿死以及竞争条件对大多数并发开发者来说都是太熟悉的概念了。Erlang和Scala都大大减轻了这种痛苦。
语言概览
Scala常被看作是下一个主要的JVM语言。它结合了面向对象编程的范式和函数式编程的范式,与Java相比有着更简洁的语法,它是静态类型的,有着跟Java一样或者有时候更快的运行速度。有太多的理由值得去认真探索一下Scala。
Erlang是一门为健壮性而生的语言,由于它的设计,它自然又是一门有着极好伸缩性的语言。它比Java历史更早,但却常被看作引领未来并发的语言。它是一门动态类型的函数式语言,有着一些非凡的系统正常运行时间的成功例子。
争论核心
那么Scala与Erlang争论的到底是什么呢?说到底,就是性能表现与伸缩能力,但这争论也包括了其它像风格,语言特性以及库支持等等。这场争论开始于Ted Neward有一次无心的给出了他对几种语言的看法,并称“[Erlang]在其自己解释器上运行事实上[是]很差的”。
Steve Vinoski与Ted于是展开了几轮争论,但这一讨论很快转移到了更多的博客上,争论的焦点也转变成了Scala与Erlang之间那些有趣的差异和共同点。我们将总结每个有意思的论点并给出每种语言的利弊,并表达对一些问题的各种不同看法。
可靠性
Steve Vinoski就Ted所发表的帖子进行了回应,给出了他对于“Erlang在其自己解释器上运行”的感受:
事实上,Erlang在其自己解释器上运行得,很好很强大;如若不然,不可能有如此好的可靠性,它将只是又一个面向并发的有趣但却无用的语言实验而已。
Steve谈到这个问题,就算一个语言本身可靠,它所依赖的基础也必须可靠才行。因为Erlang从骨子里就是为可靠性而设计的,从而支持并发,所以它不会受到一些并发性常见问题的影响,这主要是底层库包在并发环境下运行很好。
另一方面,Scala是站在JVM之上的,所以一个重要卖点在于可潜在地使用所有现成的Java代码。然而,大部分的Java代码并非专为并发而设计的,使用Scala代码时要将此考虑进去。
轻量级进程
要运行大规模并发应用,你需要大量的并行执行。这可以通过几种方式达到。使用线程是一种常见的方式,使用进程又是另一种。其区别之处在于,线程与其它线程之间共享内存,而进程是相互独立的。这意味着线程需要像互斥信号这样的锁机制,防止两个线程在同一时间对同一内存进行操作,但进程不会受此问题影响,相反是使用一些消息传递机制来跟其它的进程间通信。但进程在性能和内存方面的代价是昂贵的,这正是人们就算知道基于线程的并发是一种极复杂的编程模型也宁愿选择它的原因。
Steve Vinoski这样写到:
提供互不共享的轻量级进程架构将使得大规模并发能力变得十分容易,但这并不意味着一旦你设计好了,剩下的就只是编程的工作那么简单。
Erlang采取了这样的并发方式。一个Erlang进程是非常轻量化的,Erlang应用常常拥有成千上万的线程甚至更多。
Scala通过基于事件的Actor从另一方面达到了同样的效果。Yariv Sadan解释说:
Scala有两种类型的Actor:基于线程或是基于事件。基于线程的Actor在重量级的OS线程内部执行。它们从不相互阻塞,但每个VM上可伸缩的Actor不会多于几千个。基于事件的Actor是简单的对象。它们是十分轻量化的,并且,像Erlang进程一样,因此它们可以在一台现代的机器上数以百万计的产生。
Yariv解释到,尽管如此,这里面也还是有一些区别的:
与Erlang进程的区别之处在于,每个OS线程内部,基于事件的Actor是顺序执行的并且使用没有强占式调度算法。这使得一个基于事件的Actor可能在很长一段时间内阻塞其OS线程(甚至是无限的)。
不可变性
Erlang是一门函数式语言。这意味着其数据是不可变的,像Java的String一样,并且没有副作用带来的风险。对数据的任意操作会产生一个该数据新的修改后的版本,但原数据仍然不变。在谈到健壮性的时候,不可变性是其需要高度注意的一个因素,因为没有代码可以无意间修改其它代码依赖的数据,但从并发的观点来看,不可变性也是一个十分重要的特性。如果数据不可变,其被两个并行执行路径更改的风险就不存在,因为没有办法改变它且不需要保持同步,所以数据可以被拷贝到其它机器上。
因为Scala构建在JVM之上,结合了面向对象和函数式方法的特点,它不具备像纯函数式语言的不可变性的保证。然而,在Yariv日志的评论部分,Yariv和David Pollack就这两门语言之间的差别展开了一场有趣的讨论。David,Scala Web框架Lift的作者,给出了他对于不可变性的看法:
不可变性 —— Erlang强制了这一点,而且你几乎无法绕过它。但是,与强制一个单一类型相比,你可以用Scala神奇强大的类型系统的剩余部分去交换。我在进行Scala Actor编码时使用不可变数据,而让Scala的类型系统负责其它类型。
Yariv问到:
只发送不可变类型难道不是一个重大限制吗?这意味着,例如,你不能从Hibernate装载一个简单的bean并将它发送给其它Actor。
David回答到:
我曾基于Scala的Actor构建个多个生产系统。实际上对于不可变性问题并没有多少工作需要处理。你只需要将你的相关类(消息)定义为不可变的,其它的就不用管了。
类型系统
Erlang是动态类型的,而Scala是静态类型的并且相比Java有着更强的类型系统。然而,与Java相比最大的一个区别是Scala可以类型推断。这意味着你可以省掉大部分的类型注解,使得代码更加干净而编译器照样会做所有的检查。
关于动态与静态系统之间孰是孰非的争论看来永远也不会停止,但Erlang和Scala之间却有着显而易见的区别。
尾递归或是循环
Yariv又提到:
函数式编程与递归从来都是形影不离的。实际上离开了尾递归你很难写出有用的Erlang程序,那是因为Erlang没有循环——它对一切都使用递归(这在我看来是一件好事 :))。
这显然使得Erlang与Scala产生了很大差别。Scala提供了很多更传统的迭代,但David Pollack并没看出在这种环境下尾递归有什么优势:
尾递归——对基于事件的Actor来说根本不是什么问题。
如此说来,这仅仅有关你的偏爱和风格罢了。
热交换代码
由于Erlang是为可靠性而生的,热交换代码(运行时替换代码)是其内建的天性。
JVM对热交换代码有所支持。类可以被改变,但由于其静态的类型系统,其方法签名是不可改变的——只有其内容可以改变。虽然有第三方工具致力于此,也有框架(提倡以一种使运行时更方便交换类的编程风格书写代码),但就算运行在JVM上,如何进行交换仍是取决于你的Scala Actor是如何构建的。Jonas Bonér就此给出了一个详尽的例子。
总结
Scala和Erlang都是致力于解决多核危机的语言。它们来自不同的背景和年代,因此对待某些问题的方式也不尽相同,然而在许多方面它们的共识大于分歧,至少在并发性上如此。
Erlang已经有着数十年的历史,并且已经在许多关键的真实系统中证明了自己。其不足之处在于它有一点像一个孤岛,最近的多语言编程的趋势似乎对Erlang社区影响不大。
另一方面,Scala是同一类型应用的新生儿。一些真实应用即将诞生,并且一些公司将未来押在了上面。Scala相对Erlang的最大优势在于,它运行在JVM之上并且可以利用所有现成Java代码、框架和许多工具。话虽如此,这种强大的能力也要求了更大的责任,因为大部分Java代码不可能自动适应Scala的Actor模型。
对于主流语言无法帮开发者解决的压力越来越大的问题,两种语言都对提供了相似的解决途径。希望你在读完这篇争论总结之后,能更清楚哪种语言更适合你的特殊要求,并对其深入了解。
未来是多核的。Scala和Erlang将会越来越流行。
查看英文原文:The multicore crises: Scala vs. Erlang
原文:http://tech.sina.com.cn/s/2008-07-09/0952725490.shtml
2009年5月7日 星期四
【转】MIDlet的生命周期的深入理解及游戏死机问题
今天在查加密算法是无疑中看到的。虽然开发j2me的时候,我都这么做的。只是没考虑过不这么做的问题。这样做只是习惯,觉得这样写比较舒服,呵呵。今天看到这篇文章发现原来还能防止这些,转来学习下。
首先在你运行一个程序的时候,JAM会调用该midlet的构造函数来生成midlet的对象,然后被jam置于Paused状态。一旦jam认为这个midlet对象可以执行时,jam就会调用startApp()方法,并将此midlet置于Active状态。startApp()方法由于在系统来电、或者退回到系统菜单返回时会被再次调用,所以这里只可以放初始化一次的代码。或者你把初始化一次的代码放到midlet的构造函数中。例如:
public class Midlet extends MIDlet{
Display display = null;
MyCanvas can;
public Midelt(){
display = Display.getDisplay(this);
can = new MyCanvas();
}
public void startApp(){
display.setCurrent(can);//如果把can = new MyCanvas()放到这里,再来电返回时就会出问题。
}
}
或者
public class Midlet extends MIDlet{
Display display = null;
MyCanvas can;
public Midelt(){
}
public void startApp(){
if(display ==null){
display = Display.getDisplay(this);
can = new MyCanvas();
}//此处只会被运行1次,这样就不会出错
display.setCurrent(can);//这句按理放到这里最合适,你想显示那个canvas就放哪个!
}
}
在startApp()中,你调用display.setCurrent(can)的时候,首先运行的是showNotify(),接着运行paint()函数一次,如果有线程的话,此时run()方法开始运行。一般在run()方法里一般这么写。此时的run()是可以处理异步事件的,也就是你来电话的时候,这里run()还是运行的。不过他不会paint()什么东西,即使它里面有repaint(),这点放心。
public void run(){
while(flag){//flag是boolean型变量
try{
Thread.sleep(50);//时间自己设啦。
}catch(Exception e){}
repaint();
}
}
哇~~来电话了,或者你退到系统菜单。如nokia s60的手机。
hideNotify()首先会被调用,接着pauseApp()再被调用。
这么快,打完了,返回时:先调用showNotify(),接着调用paint()函数一次,最后才是调用startApp()函数。
关于run()和paint()也可以使用display.callSerially(this)语句。这个以后有时间了再说。
明白了生命周期,再来看死机问题。我说的死机问题,多是来电话返回时死机。其实只要找到了问题,一切就变的很简单。
为什么死机,归根结底还是程序问题。好像是废话。哈~~
Graphics mg;//定义的全局参数
paint(Graphics g){
mg = g;//有的程序这样写,if(mg ==null){mg =g:}这样对于n7610系列就会出错。
mg.drawString();
switch(case){
case GAME_MUNE:
drawA();
break;
case PLAY:
drawB();
break;
default:
break;
}
}
/*下面的画图函数一定要放到paint()函数里调用,不要在别的地方调用,如run()里面,上面说过,程序暂停之后返回,会先paint()一次,如果在别的地方调用就会出现问题。*/
public void drawA(){
mg.drawString();
}
public void drawB(){
mg.drawString();
}
按照上面的写法一般不会出现死机问题。当然,你也可以不定义全局的mg,可以把g单独传到各个画图子函数中。如,
paint(Graphics g){
g.drawString();
switch(case){
case GAME_MUNE:
drawA(g);
break;
case PLAY:
drawB(g);
break;
default:
break;
}
}
public void drawA(Graphics mg){
mg.drawString();
}
public void drawB(Graphics mg){
mg.drawString();
}
原帖:http://azi.javaeye.com/blog/194478
首先在你运行一个程序的时候,JAM会调用该midlet的构造函数来生成midlet的对象,然后被jam置于Paused状态。一旦jam认为这个midlet对象可以执行时,jam就会调用startApp()方法,并将此midlet置于Active状态。startApp()方法由于在系统来电、或者退回到系统菜单返回时会被再次调用,所以这里只可以放初始化一次的代码。或者你把初始化一次的代码放到midlet的构造函数中。例如:
public class Midlet extends MIDlet{
Display display = null;
MyCanvas can;
public Midelt(){
display = Display.getDisplay(this);
can = new MyCanvas();
}
public void startApp(){
display.setCurrent(can);//如果把can = new MyCanvas()放到这里,再来电返回时就会出问题。
}
}
或者
public class Midlet extends MIDlet{
Display display = null;
MyCanvas can;
public Midelt(){
}
public void startApp(){
if(display ==null){
display = Display.getDisplay(this);
can = new MyCanvas();
}//此处只会被运行1次,这样就不会出错
display.setCurrent(can);//这句按理放到这里最合适,你想显示那个canvas就放哪个!
}
}
在startApp()中,你调用display.setCurrent(can)的时候,首先运行的是showNotify(),接着运行paint()函数一次,如果有线程的话,此时run()方法开始运行。一般在run()方法里一般这么写。此时的run()是可以处理异步事件的,也就是你来电话的时候,这里run()还是运行的。不过他不会paint()什么东西,即使它里面有repaint(),这点放心。
public void run(){
while(flag){//flag是boolean型变量
try{
Thread.sleep(50);//时间自己设啦。
}catch(Exception e){}
repaint();
}
}
哇~~来电话了,或者你退到系统菜单。如nokia s60的手机。
hideNotify()首先会被调用,接着pauseApp()再被调用。
这么快,打完了,返回时:先调用showNotify(),接着调用paint()函数一次,最后才是调用startApp()函数。
关于run()和paint()也可以使用display.callSerially(this)语句。这个以后有时间了再说。
明白了生命周期,再来看死机问题。我说的死机问题,多是来电话返回时死机。其实只要找到了问题,一切就变的很简单。
为什么死机,归根结底还是程序问题。好像是废话。哈~~
Graphics mg;//定义的全局参数
paint(Graphics g){
mg = g;//有的程序这样写,if(mg ==null){mg =g:}这样对于n7610系列就会出错。
mg.drawString();
switch(case){
case GAME_MUNE:
drawA();
break;
case PLAY:
drawB();
break;
default:
break;
}
}
/*下面的画图函数一定要放到paint()函数里调用,不要在别的地方调用,如run()里面,上面说过,程序暂停之后返回,会先paint()一次,如果在别的地方调用就会出现问题。*/
public void drawA(){
mg.drawString();
}
public void drawB(){
mg.drawString();
}
按照上面的写法一般不会出现死机问题。当然,你也可以不定义全局的mg,可以把g单独传到各个画图子函数中。如,
paint(Graphics g){
g.drawString();
switch(case){
case GAME_MUNE:
drawA(g);
break;
case PLAY:
drawB(g);
break;
default:
break;
}
}
public void drawA(Graphics mg){
mg.drawString();
}
public void drawB(Graphics mg){
mg.drawString();
}
原帖:http://azi.javaeye.com/blog/194478
2009年4月25日 星期六
【转】女大学生日记一则(令人震撼)
今天无意在某个学长的博客中看到这篇文章,是蛮早前的了。“令人震撼”这四个字是学长的标题。看完后,把我震撼了么,只是有点感觉。换作以前的我一定感慨良多,现在只是觉得很现实。觉得替这位老人难过,仅此而已。
原文如下:
我只是一个学生,无权无势,但却做梦也没有想到,居然有人向我下跪。
那是数天前的一个中午,我刚从双安商场的美食城出来,走上人行天桥,凛冽的寒风在我暴露的皮肤上肆虐不已。突然看见前面有一满头银发的老妪不停地向人打躬作揖,而路人纷纷掩鼻而走。估计又是一个乞丐,我正在这么想着。这时,老者却向我走来。我摸了摸口袋中的硬币,心想也许又是一个骗子。我几乎都能猜到她会说些什么,无非是来京访亲,找不到人了,好些天没有吃饭了等引人入套的话。我做好了用几个钢崩将她打发的准备,不料老人却用地道的河南话对我说,「同志,海淀区司法援助中心怎么走?」喔,原来只是问路,我笑了笑,感觉自己有点神经过敏。「对不起,我也不知道」,我感到有些不好意思,但自己确实不知那个援助中心在哪。老人朝我点了点头,又向旁边一个路人询问,但对方却并未理睬这个貌似乞丐的老人。我禁不住又打量了一下老人,她估摸60多岁,带着数个破破烂烂的编织袋和一个古老的黑色旅行袋,袋子旁还用玻璃绳子栓着一个破水杯。又是一个上访者,一个不知被多少个部门像中国足球一样被人踢来踢去而始终踢不进门的上访者,我心里一阵难受,对老人说,「您别急,我帮您打电话问一问」。我用手机给查号台打了电话,在现代科技的帮助下,很快问到了援助中心的地址--某某路某号。这时老人突然扑通给我跪下,泣不成声地对我说:「你是个好人」。天啊,仅仅是问个路,一个六旬开外的老人居然向我下跪。
我的眼睛有点湿润,慌忙把老人扶起。她只是一个劲地对我说你是个好人,你是个好人。我给她指了指援助中心的方向,告诉她该怎么坐车。老人从贴身的内衣中小心翼翼地掏出个皱巴巴的信封,颤巍巍的记下了地址。我本想迅速撤离这个让人压抑的天桥,可又觉得即使指明方向、地址,对于这个对北京人生地不熟的老人来说,要想找到那个连我都不易找到的援助中心无疑是大海捞针。于是我决定带她去,不料就为这她再次向我下跪,我措手不及,只能一手提起了她那像垃圾一样的编织袋,一手把她扶起。
在去往目的地的出租车上,老人告诉我,她是河南南阳人,今天早上刚到北京,为了找援助中心,已经徒步走了4个多小时。她问了问我的身份,当我告诉她我还是学生时,她又一次哭了,哽咽的说到:「如果不是家里穷的话,我那儿子现在也是大学生,也就不会遭这个罪了。」原来他的儿子是油漆工,两年前来京打工。一天深夜,她儿子骑着自行车,带着铁桶和毛笔正往家赶,突然被几个巡逻的警察二话不说地抓了起来。没有申辩、没有审判、似乎没有任何程序,孩子就被关进了监房。过了20多天,事情总算是弄清了,孩子的清白也得到了证明,但他的手指却由于不知名的原因掉了几个,而且精神彻底崩溃,成了疯子。想像一下吧,一个来北京寻求希望、身心健康的年青人,在毫无过错的情况下,莫名其妙地深陷囹圄,没有任何反抗、任何辩解的机会,最终成了一个废人。
「法律面前人人平等」在这个事实面前是何等地苍白,一个打工者,仅仅因为穿着寒碜就会被怀疑为嫌疑份子,而那些开着大奔、西装革履却暗地里坐着违法勾当的「款爷」们就能理所当然地避免这样的「天灾人祸」,甚至还会备受尊敬。难道我们的法律中有「以衣着和相貌」这样的定罪原则吗?「人生而自由,却无往不在枷锁之中。」我感到了人类的渺小,感到了法律的悲哀,「相信法律吧」,这就是我,一个研读法律近10年的人对她唯一能说的话,一句苍白得近乎虚伪的话。
到了援助中心,我执意要陪她上去,但老人对我鞠了鞠躬,说已经很感谢我了,让我不要上去,她说我还年轻,不要介入这种可能影响将来前途的事情。
我走了,想着老人的话,突然感觉自己是多么的卑微,多么的懦弱,感到自己曾经奋笔疾书的有关法律精神的探讨是多么的可笑,多么的幼稚。
深夜,我又想起了这位老人,不知在这寒冷的冬夜里,她栖息何处?
原文如下:
我只是一个学生,无权无势,但却做梦也没有想到,居然有人向我下跪。
那是数天前的一个中午,我刚从双安商场的美食城出来,走上人行天桥,凛冽的寒风在我暴露的皮肤上肆虐不已。突然看见前面有一满头银发的老妪不停地向人打躬作揖,而路人纷纷掩鼻而走。估计又是一个乞丐,我正在这么想着。这时,老者却向我走来。我摸了摸口袋中的硬币,心想也许又是一个骗子。我几乎都能猜到她会说些什么,无非是来京访亲,找不到人了,好些天没有吃饭了等引人入套的话。我做好了用几个钢崩将她打发的准备,不料老人却用地道的河南话对我说,「同志,海淀区司法援助中心怎么走?」喔,原来只是问路,我笑了笑,感觉自己有点神经过敏。「对不起,我也不知道」,我感到有些不好意思,但自己确实不知那个援助中心在哪。老人朝我点了点头,又向旁边一个路人询问,但对方却并未理睬这个貌似乞丐的老人。我禁不住又打量了一下老人,她估摸60多岁,带着数个破破烂烂的编织袋和一个古老的黑色旅行袋,袋子旁还用玻璃绳子栓着一个破水杯。又是一个上访者,一个不知被多少个部门像中国足球一样被人踢来踢去而始终踢不进门的上访者,我心里一阵难受,对老人说,「您别急,我帮您打电话问一问」。我用手机给查号台打了电话,在现代科技的帮助下,很快问到了援助中心的地址--某某路某号。这时老人突然扑通给我跪下,泣不成声地对我说:「你是个好人」。天啊,仅仅是问个路,一个六旬开外的老人居然向我下跪。
我的眼睛有点湿润,慌忙把老人扶起。她只是一个劲地对我说你是个好人,你是个好人。我给她指了指援助中心的方向,告诉她该怎么坐车。老人从贴身的内衣中小心翼翼地掏出个皱巴巴的信封,颤巍巍的记下了地址。我本想迅速撤离这个让人压抑的天桥,可又觉得即使指明方向、地址,对于这个对北京人生地不熟的老人来说,要想找到那个连我都不易找到的援助中心无疑是大海捞针。于是我决定带她去,不料就为这她再次向我下跪,我措手不及,只能一手提起了她那像垃圾一样的编织袋,一手把她扶起。
在去往目的地的出租车上,老人告诉我,她是河南南阳人,今天早上刚到北京,为了找援助中心,已经徒步走了4个多小时。她问了问我的身份,当我告诉她我还是学生时,她又一次哭了,哽咽的说到:「如果不是家里穷的话,我那儿子现在也是大学生,也就不会遭这个罪了。」原来他的儿子是油漆工,两年前来京打工。一天深夜,她儿子骑着自行车,带着铁桶和毛笔正往家赶,突然被几个巡逻的警察二话不说地抓了起来。没有申辩、没有审判、似乎没有任何程序,孩子就被关进了监房。过了20多天,事情总算是弄清了,孩子的清白也得到了证明,但他的手指却由于不知名的原因掉了几个,而且精神彻底崩溃,成了疯子。想像一下吧,一个来北京寻求希望、身心健康的年青人,在毫无过错的情况下,莫名其妙地深陷囹圄,没有任何反抗、任何辩解的机会,最终成了一个废人。
「法律面前人人平等」在这个事实面前是何等地苍白,一个打工者,仅仅因为穿着寒碜就会被怀疑为嫌疑份子,而那些开着大奔、西装革履却暗地里坐着违法勾当的「款爷」们就能理所当然地避免这样的「天灾人祸」,甚至还会备受尊敬。难道我们的法律中有「以衣着和相貌」这样的定罪原则吗?「人生而自由,却无往不在枷锁之中。」我感到了人类的渺小,感到了法律的悲哀,「相信法律吧」,这就是我,一个研读法律近10年的人对她唯一能说的话,一句苍白得近乎虚伪的话。
到了援助中心,我执意要陪她上去,但老人对我鞠了鞠躬,说已经很感谢我了,让我不要上去,她说我还年轻,不要介入这种可能影响将来前途的事情。
我走了,想着老人的话,突然感觉自己是多么的卑微,多么的懦弱,感到自己曾经奋笔疾书的有关法律精神的探讨是多么的可笑,多么的幼稚。
深夜,我又想起了这位老人,不知在这寒冷的冬夜里,她栖息何处?
2009年4月21日 星期二
oracle 收购 sun 是福是祸 是挑战
刚才才看到这条消息,确实晚了点,这么震撼的消息现在才知道惭愧。
当时传ibm收购sun,网上议论纷纷。当谈判破裂时,很多分析师说是收购失败是sun的损失,也有说是ibm的损失等等。我当时没有觉得什么损失不损失的。大家维持原状有什么损不损失的。现在oracle又是用现金收购了sun。一方面可见oracle这几年来收购的野心,另一方面可见到现在可谈损不损失的问题了。
无疑对于ibm来说是损失了。现在oracle借助sun的软硬件技术,将成为IBM在数据中心领域的一个强大竞争对手,新公司可以销售包括硬件、操作系统和架构软件在内的完整企业产品组合,而在以前只有IBM才能够提供如此完整的产品和服务。
很多人说java前途光明。我不觉得。现在oracle形成了高端java企业开发一条龙,可以说有垄断之势。对于以前同是以java作为开发语言的ibm,sap等大公司对java有所忌惮。如何处理好两者之间的关系,就看oracle的操作了。作为java的开发者现在感觉就像是我为鱼肉的感觉。
对于oracle来说,sun的硬件部分的合并,让他不再是一家软件公司了,而变成了系统厂商。这也就让从前合伙的戴尔和惠普,有所忌惮了。对于oracle来说当然是扩张的好事。但对于从事这方面的开发人员来说,可选性变小了。更本不是件好事。
我一直觉得当时ibm收购失败是件好事,没有什么损不损失的。sun处于中间位置,达到平衡。所有的厂商以java技术而不用过多担心。现在格局被打破了,我对java的将来感到担心。
我对mysql也情有独钟,小巧轻便。现在mysql真是尴尬,所有的猜测都取决于oracle的决策了。mysql实在不行就去试试PostgreSQL。但是java的前提,我很在意。java确实有很多缺点,但是真是一门好语言啊。真不想因此而减少了他的应用范围。
是福是祸 都是挑战。接下来举世瞩目oracle的决策吧。希望都是明智的。但愿。。。。
当时传ibm收购sun,网上议论纷纷。当谈判破裂时,很多分析师说是收购失败是sun的损失,也有说是ibm的损失等等。我当时没有觉得什么损失不损失的。大家维持原状有什么损不损失的。现在oracle又是用现金收购了sun。一方面可见oracle这几年来收购的野心,另一方面可见到现在可谈损不损失的问题了。
无疑对于ibm来说是损失了。现在oracle借助sun的软硬件技术,将成为IBM在数据中心领域的一个强大竞争对手,新公司可以销售包括硬件、操作系统和架构软件在内的完整企业产品组合,而在以前只有IBM才能够提供如此完整的产品和服务。
很多人说java前途光明。我不觉得。现在oracle形成了高端java企业开发一条龙,可以说有垄断之势。对于以前同是以java作为开发语言的ibm,sap等大公司对java有所忌惮。如何处理好两者之间的关系,就看oracle的操作了。作为java的开发者现在感觉就像是我为鱼肉的感觉。
对于oracle来说,sun的硬件部分的合并,让他不再是一家软件公司了,而变成了系统厂商。这也就让从前合伙的戴尔和惠普,有所忌惮了。对于oracle来说当然是扩张的好事。但对于从事这方面的开发人员来说,可选性变小了。更本不是件好事。
我一直觉得当时ibm收购失败是件好事,没有什么损不损失的。sun处于中间位置,达到平衡。所有的厂商以java技术而不用过多担心。现在格局被打破了,我对java的将来感到担心。
我对mysql也情有独钟,小巧轻便。现在mysql真是尴尬,所有的猜测都取决于oracle的决策了。mysql实在不行就去试试PostgreSQL。但是java的前提,我很在意。java确实有很多缺点,但是真是一门好语言啊。真不想因此而减少了他的应用范围。
是福是祸 都是挑战。接下来举世瞩目oracle的决策吧。希望都是明智的。但愿。。。。
2009年4月14日 星期二
一切就是那么的命中注定
今天在线上碰到了男人,问他最近境况。后得知现在在一家国企混着,等世嘉的下次面试。
呵呵,将兴趣变成了自己的工作到还真是不错。后来聊着聊着,聊到了面试第一轮的一道题。
写个一个通用的y=Asin(ax+b)+c的解法..要时间复杂越短越好。
他问我的时候,我一下子懵了下。好久没有接触高等数学了(惭愧)。依稀记得以前有什么公式可以通解。但要我立马不翻书,可真是不行了。男人说:...你们都是往这里想的.桃子也是...
。。。。我哪里想错了么?男人说:我就说把y=sinx的值按照精度要求预先存在数组中。
哈哈哈哈哈,用空间换时间么。桃子说他肯定错,我不觉得。至少别人让他面试到现在是不假的事实。我也觉得不错的方法。第一,你的算法再怎么牛,能达到系统预设的sin求解不是件容易的事情。第二:现在的要求是自己写一个要求时间复杂越短越好,当然是用空间去换时间了。我和桃子都一上来就走入误区了。
我很好奇,他当时怎么会突发如此想法的。我想正常人大多会和我和桃子的想法一样,想一个算法来解。男人说反正我看到过别人这么说.就觉得不至于不可行。
是的,也许不是他当时的突发奇想。但是平时的积累就是财富。你平时无意中捡起来的某些东西,也许暂时没用,但是总有用处的一天。一切就是这么命中注定。
呵呵,将兴趣变成了自己的工作到还真是不错。后来聊着聊着,聊到了面试第一轮的一道题。
写个一个通用的y=Asin(ax+b)+c的解法..要时间复杂越短越好。
他问我的时候,我一下子懵了下。好久没有接触高等数学了(惭愧)。依稀记得以前有什么公式可以通解。但要我立马不翻书,可真是不行了。男人说:...你们都是往这里想的.桃子也是...
。。。。我哪里想错了么?男人说:我就说把y=sinx的值按照精度要求预先存在数组中。
哈哈哈哈哈,用空间换时间么。桃子说他肯定错,我不觉得。至少别人让他面试到现在是不假的事实。我也觉得不错的方法。第一,你的算法再怎么牛,能达到系统预设的sin求解不是件容易的事情。第二:现在的要求是自己写一个要求时间复杂越短越好,当然是用空间去换时间了。我和桃子都一上来就走入误区了。
我很好奇,他当时怎么会突发如此想法的。我想正常人大多会和我和桃子的想法一样,想一个算法来解。男人说反正我看到过别人这么说.就觉得不至于不可行。
是的,也许不是他当时的突发奇想。但是平时的积累就是财富。你平时无意中捡起来的某些东西,也许暂时没用,但是总有用处的一天。一切就是这么命中注定。
订阅:
帖子 (Atom)
