Archive for the ‘Java’ Category

Dalvik虚拟机

星期三, 12月 2nd, 2009

昨天开始看Android相关的技术文章,Android里面使用了一个名为dalvik的虚拟机来支持java。

Dalvik是一个register-based 的虚拟机,register-based是相对stack-based而言的,register-based的操作数是放在寄存器里面的,因此每条指令都需要指明操作的是哪个寄存器,而stack-based的操作数是放在栈上,指令从栈顶pop出操作数操作,然后把结果push回栈即可。

因此stack-based对指令的要求低,对内存的要求高,而register-based对指令的要求高,对内存的要求低。

尽管Dalvik被视为一种Java Virtual Machine,然而其指令字节码是跟JVM不相同的,需要通过一个专用工具,把java的类文件转为.dex(Dalvik Executable)格式。

再过了一下Dex的文件格式,设计得还挺简单,20分钟就可以浏览完了。

Spark启动提速

星期四, 4月 2nd, 2009

项目使用spark作为基础,加了不少内容,基本上是只增不删,等到做得差不多了,便开始砍掉那些不用的代码。

测量了一下,界面方面多余的组件初始化的时候消耗得特别多,砍掉。再优化了一些加载逻辑,最后发现还是比较长的启动速度。

于是启用final大法,虽然spark类早已声明成final的,然而spark类的实例化的过程却不是final的。更改了一下:

[snippet=13700]

这样编译的时间长了很多,然而启动速度有了质的飞跃。

在ant里面使用pmd

星期一, 10月 27th, 2008

ant是用来编译java项目的一个工具。其主页是:http://ant.apache.org/

pmd是一个源代码检查器。其主页是:http://pmd.sourceforge.net/

pmd提供了开放性的源代码检查功能,当然最常用的是检查类里面的无用私有成员,方法里面无用临时变量,以及方法定义里面的无用参数等等。

下载pmd压缩包之后,解压后可以直接用其中的pmd.jar对源代码进行检查。例如:

c:\> java -jar pmd-4.2.4.jar c:\my\source\code text unusedcode,imports -targetjdk 1.5 -debug

  • text是指输出的结果为text格式,可以将上述命令重定向别的文件。
  • unusedcode,imports是检查无用代码和无用import语句。
  • -targetjdk 1.5是指定jdk的版本为1.5。
  • -debug是调试模式。

然而我们的项目是用ant来编译的,所以希望把pmd集成到ant中。看了一下帮助,稍改动一下:

1.将pmd的lib下的jar文件都copy到项目的build目录下的pmd目录中。

2.打开build.xml,添加如下部分:

<path id=”pmd.classpath”>
<pathelement location=”${basedir}/”/>
<fileset dir=”build/pmd/”>
<include name=”*.jar”/>
</fileset>
</path>
<target name=”pmd”>
<taskdef name=”pmd” classname=”net.sourceforge.pmd.ant.PMDTask” classpathref=”pmd.classpath”>

</taskdef>
<pmd rulesetfiles=”unusedcode”>
<formatter type=”html” toFile=”pmd_report.html” toConsole=”true”/>
<fileset dir=”${basedir}/src/”>
<include name=”**/*.java”/>
</fileset>
</pmd>
</target>
其中path部分是定义jar的目录为pmd.classpath,${basedir}就是项目所在目录,

target部分就是执行pmd的部分,taskdef定义了执行该任务的类是net.sourceforge.pmd.ant.PMDTask,其类路径为pmd.classpath。pmd 部分是pmd的执行设置,rulesetfiles指定其检查类型为unusedcode,formatter是结果输出文件。fileset是被pmd检查的文件目标路径。

保存build.xml之后,可以用ant pmd来执行检查,要显示检查过程,可以用ant -v pmd。

虚拟机版本导致修改 JOptionPane

星期一, 10月 13th, 2008

今天update了一下代码,也可能是我太久没有在自己的机器上编译valuelive了,一上来就给我报个错:

    [javac] C:\src\zm\CVS\spark\src\java\org\jivesoftware\sparkimpl\profile\
ChangeAvatarFrame.java:138: 找不到符号
    [javac] 符号: 方法 createDialog(java.lang.String)
    [javac] 位置: 类 javax.swing.JOptionPane
    [javac]             dialog = dialogOptionPane.createDialog(Res.getString
("title.select.avatar"));

有点懵了,问问别人,都没有问题。于是ant clean再ant,发现依然如故。

查一下这个文件,是7月份commit的,他们都是用1.6的jdk编译,我一直没装新的jdk,还在用1.5。于是查了一下,原来1.5的swing里面,JOptionPane的createDialog有两个参数Component和String,而1.6只有1个String。

把代码改了一下,在createDialog里面加了个null就好了。

在Java程序中插入swf文件的一些方法

星期三, 10月 8th, 2008

目前RIA处于一个过渡时期,一方面桌面程序的网络能力远没有浏览器上的应用程序强大,另一方面浏览器上的应用程序又由于安全限制而缺乏访问本地硬盘的能力。虽然云计算等概念看上去很美,但谁放心把重要的数据依赖于一个很可能别人能顺利访问而自己可能失控的网络呢。

说得多了。

有这样的需求,Flash/Flex做出来的swf很漂亮,网络访问能力也好,而Java的客户端想将其集成进去,怎么做?

1.由于播放swf的是flashplayer,于是有人用java写了一个flashplayer,称为Jflashplayer。Java程序可以用这个Jflashplayer来播放swf,从而做到了Java中集成swf的效果。

这个方案按道理来说比较正统,缺点有两个

  • Jflashplayer并不完全支持swf的所有特性,只是有选择地支持,因此一些使用高级版本flash/flex开发的程序中用到的API可能得不到支持。
  • Jflashplayer价格相对来说比较贵,并不是所有的开发者都支付得起的。

目前我们的项目采取的则是另一种方法。

2.由于Java的官方开发团队提供了JDIC (JDesktop Integration Components)的软件包,可以在Java程序中直接集成操作系统的浏览器(比如IE)来实现浏览器功能,因此,首先在程序中使用JDIC集成一个NativeBrowser,然后在NativeBrowser中播放含swf文件的网页,也同样可以满足这个需求。

这个方案需要解决的问题是,如何让网页中flash程序与java程序进行数据交互。

Java程序访问/调用flash:NativeBrowser中提供了executeScript的方法,可以执行内置网页中的javascript程序,而对网页和flash程序进行适当的配置,又可以通过javascript调用/访问flash中的方法和数据。

flash程序访问/调用Java:先按上述的方法,在网页中的javascript和flash之间建立好访问机制。再通过javascript里提供的设置document.title的方法修改网页标题为合适的数据,同时,在NativeBrowser类中监听网页的titleChanged事件。在事件处理中,判断网页标题是否为flash触发的回调,若是,则执行java端的方法,并通过executeScript方法返回结果给网页,再到flash。

目前未发现这种方法不适用的地方,只是java->javascript<->flash这个过程稍显低效,而titleChanged的方式更是属于优先级较低的事件触发,在flash需要频繁调用java的场合可能会遇到些麻烦。

=======================================================

在人力和财力支持的条件下,应当开发功能完善的基于java的flashplayer,则上述问题则不复存在。

Java的字符串问题

星期五, 9月 5th, 2008

String s=”hello”;
String t=”hello”;
System.out.print(s==t);//true
?
String s=new String(”hello”);
String t=new String(”hello”);
System.out.print(s==t);//false
在两个地方,s和t的字符串内容都是hello,为什么前一个==会为true,而后一个则是false呢?

core Java的答案:

If the virtual machine would always arrange for equal strings to be shared, then you could use the == operator for testing equality. But only string constants are shared, not strings that are the result of operations like + or substring. Therefore, never use == to compare strings lest you end up with a program with the worst kind of bug—an intermittent one that seems to occur randomly.

直白一点的:

一般String常量会有一个常量池,里面放程序里出现的String常量。
当写String s=”hello”;就是声明一个叫s的引用指到常量池里那个对应的String对象上,所以你直接这么写的话,用==比较就是一样的,因为他们都指的是常量池里的那个String对象。

new的话就不一样了,后面写的那个,可以理解成用String常量池里的那个对象去调用String的构造函数,构造出一个新的String对象,这样再比较的引用肯定就不一样了,因为每次都是构造一个新的对象。