2010年6月27日星期日

很久没来这里了。。

大学毕业快一年了,天朝封闭blogger也一年多了吧。现在通过某跳板,回来看看去年的我的文章,感觉现在没了当时憧憬,当时的冲劲。。。 也许是工作了,现实了,累了。。(有点过了吧。。。)

いつでも自分の夢を持って、前に向けて、少しでも進むというのは、今考えると難しいな。

好了,发现便捷的回来的方法了,偶尔来图两笔吧^0 ^。

2009年8月9日星期日

感触

最近真是忙的无话可说,这里也很久没来了。 昨天发现一些很有感触的话语。本来想发到饭否上的,没想到饭否被和谐了。。。

那就发这里了。

有时转变不一定成功 但有时 转变已经是一个新的开始

再niuB的肖邦也弹不出老子的悲伤

怀才就像怀孕,时间久了才能让人看出来

唯女人与英语难过也,唯老婆与工作难找也

你以为我会眼睁睁看你死去么,我会闭上眼的

您认识的人越多,就越喜欢动物

再讨厌别人,再看透世界,再悲观,您对几个人好,总还是会被几个人关心和接受的。
这就是人类社会,陷阱虽多,等价交换的关怀也不是没有。
最起码,不是一个没有。

还有一个程序员上看到的笑话:

一个人在一个升空的热气球上探险旅游,后来发现迷路了,不知道他所在的位置,他将热气球下降了一些高度,找到了地面上的一个人。

  气球上的人(简称气球人)再将热气球降低了一点,大声的对地面上的那个人喊(简称地面人):“对不起,能不能告诉我,我在哪儿?”


  地面人拿出一把卷尺,目测了一阵子,然后回答道:“你现在离地面高30英尺的地方。



  气球人说:“你一定是位程序员。”

  “是啊,我是啊,你怎么知道的?”地面人反问道。

  气球人说:“因为你的答案在技术上是正确的,但是实际上一点用都没有。”

  “我知道你一定是管理人员,”地面人回应着。

  “为什么?”
  地面人回答道:“因为:你不知道你在哪里或者打算去哪里,但你却希望我给你提供帮助,就像现在的情形一样,但你却认为这是我的错。”

        不在于讽刺领导者,而在于提醒自己无论出于管理者还是被领导者,到要意识到对方的难处,去找到最为合适的解决方案。

2009年7月12日星期日

vs2005发布网页端口不一致

最近由于将来工作需要,开始看看asp.net。先上手写个hello world,发布试试。没想到一上来就遇到莫名的问题了。

症状是这样的:

IE地址栏里面显示的端口号和桌面任务栏右下角“ASP.NET Development Server”的端口不一致,而把IE地址栏的端口号改成“ASP.NET Development Server”显示的端口号,结果网页就能出来。

很是奇怪,问了平时工作就做asp的同学,他也没碰到过。后来发现网上有人列出了方法,一试果然可行。

在这里记录下,备忘吧。

解决方法:引用原文如下:“是 否安装了NOD32 3.0以上版本?或者还有其它什么防火墙类软件?如果你是安装NOD32 3.0的,按照以下方法做: 依次进入NOD32的高级设置(F5),Web访问保护,HTTP,Web浏览器,会看到一个程序列表你的devenv.exe应该在其中,双击前面的勾 (相当于去掉选中状态),确定退出,停止一切运行的ASP.NET Development Server,在VS中打开并重新编译运行你的Web程序”。

试了这个方法,可行,在此记录。

2009年6月11日星期四

java jDom异常: Content is not allowed in prolog

先交代下前提: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年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

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

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