Nowadays we are familiar with the forward and backward function of browser, but may be little of us know the real algorithm of it. In a recent project, I have to simulate a forward-backward function for our ajax based web application. So I spend some time on the forward-backward algorithm of Chrome. Read the rest of this entry »
Posted by Wayne Wan in About Work, websphere on 12-01-2011
JDBCProvider向Websphere Message Broker(WMB)中需要操作数据库的node提供数据库连接服务,JDBCProvider作为一个服务被注册到指定的broker中。
这里需要涉及到的几条命令有:
- mqsideleteconfigurableservice, 用于删除一个可配置的服务对象。
例如:mqsideleteconfigurableservice MB7BROKER -c JDBCProviders -o SIMPLERROUTEDB
表示从MB7BROKER这个broker中删除type为JDBCProviders的服务(configurable service)中的名为SIMPLERROUTEDB可配置对象(configurable service object).
- mqsicreateconfigurableservice,用于创建一个可配置的服务对象(configurable service)
例如: Read the rest of this entry »
项目里面大量的使用到了jakata的commin包,包括beanutils这个包,主要是用来copy bean property,以前一直用的很好,也没有去深究它内部的实现机制,评自己猜想就只是运用反射去取得属性的值,然后设置值吧。接着就出现了现在遇到的问题,项目中一个vo属性的类型为Byte包装类型,这种属性在实例化的时候默认为null,这个特性被我用到了业务中,也就是我会通过判断这个属性是否为null来实现某些逻辑,结果发现这个属性竟然会在没有任何人动的情况下自己被赋值为0,然后就导致依赖这个属性的业务逻辑错掉,debug一步一步的跟踪发现只要一经过beanutils,copy出来的bean的这个属性自动变为0了,以为是beanutils的bug,找来源码看了看,发现BeanUtils中其实是调用了BeanUtilsBean的copyProperties方法,BeanUtilsBean中实现了一个简单的工厂模式,将的一个实例绑定在当前线程中,有点儿类似ThreadLocal,也就是当前线程中所有调用都会采用同一机制进行copy,这里说到copy的机制其实就是指Converter,对于各种类型都有一个特定的Converter,包内部提供了一些jdk内部类型的Converter,每种类型Converter都有可以提供一种默认值,而在BeanUtils中对于Byte,Integer等数值类型提供的默认值是:0 ,所以就会出现把Byte类型值为null转换成了0。其实这么做也有他的好处,可以避免出现烦人的NullPointerExceprtion。知道原因,解决办法就很容易想到了,自己重新初始化一下BeanUtilBean中的ByteConverter。
开门见山,B/S架构应用程序的安装程序无非就是拷贝一些文件,检查一下环境配置,注册服务,启动服务之类的了。拷贝文件就没什么好说的了。下面着记录一下如下几点:
- 端口检查
- 读写注册表
- 调用外部可执行文件
- 注册、启动、停止服务
- 注册环境变量
Read the rest of this entry »
这两天经常听到同事说我们的系统运行一两个小时过后就会报Java HeapSpace OutOfMemory的异常,一开始我还没怎么在意这个问题,还以为是在eclipse中用debug状态运行tomcat导致的,后来又出现了几次,觉得事情有点儿不对了,检查了我的代码,基本没有什么地方会出现内存泄漏,该释放资源的地方也都释放了。一开始懒得去看同事的代码,就找了jconsole工具来分析,这不看不知道,一看才吓了一跳。查看内存占用发现大致每隔两分钟左右内存就会有一个飙升,线程数跟内存占用一样每当内存波动的时候线程数就有一个飙升,而且一上去了就不下来,查看具体的线程堆栈,发现增加的线程全部是一个snmp4j中的一个类型。这一块恰好是我那同事实现的,于是没办法只有看看他的代码了(貌似搞开发的都不愿意看别个的代码…). 在我们的系统中有一个轮询操作,在这个轮询操作中会使用到snmp4j api,查看snmp4j api发现用到的一个类中会持有socket资源并创建内部线程,这个socket会中断在那块儿,而俺那同事的实现是在每次轮询的时候都会新建一个该对象,而且在使用过后也没有close掉。查看snmp4j的源码发现该类的内部实现是有从一个内部线程池中取得一个线程,然后在该线程中用到socket,于是由于线程中的socket为关闭一直阻塞,这条新建的线程 也就没办法释放了。问题就算是找到了,下面的解决办法就很容易了,将这个地方实现为一个单例模式,最后测试的结果也很好,运行三四个小时,线程数始终保持在估计的范围内。
等有时间了,再好好写一篇jconsole的使用方法,发现这玩意儿还挺好玩儿的。
今天做一个mysql数据恢复的小程序,采用Runtime.exec的方式来执行mysql命令。主要用来恢复一些由定时程序自动备份出来的数据库文件,有时候可能会出现恢复的数据在数据库中还存在,于是会出现主键重复的错误,于是我在恢复的时候加入–force参数,手动在cmd控制台下执行可以很明显看到mysql返回了一些duplicate的error,按道理在java app中也能正常执行过去,可在执行java app的时候看控制台中打印的日志显示,程序阻塞在了waitFor这一步。我的程序片段如下:
……
p = Runtime.getRuntime().exec(cmd);
……
p.waitFor();
……
百思不得其解,最后在google了下,找到一片最早分析该原因的文章是在javaworld上。原因是操作系统这一层对输入输出流有一个buffer,由于受到这个buffer的大小限制,当buffer满了而又没有线程去读,则当前执行的线程就会阻塞掉,于是修改一下程序,开辟两个线程专门用于读取输出流,一个用于读取返回消息流,一个用于读取异常消息流,于是修改程序如下:
……
p = Runtime.getRuntime().exec(cmd);
new PrintStream(p.getInputStream()).start();
new PrintStream(p.getErrorStream()).start();
p.waitFor();
……
此处PrintStream为一个读取inputstream的线程。
串口通信这词儿听上去跟java似乎有点儿沾不上边儿,因为java大多是拿来做大规模企业应用的,像串口通信这种很底层的东东一般都会用比较低级别的语言来做,但最近就遇到了这么一事儿,于是google了下,没想到还真能用java做,要用到的是javax扩展类库javacomm,它是一系列的标准,该类库在sun的官网上只提供linux版本。由于我所应用的平台是win32,所以还得去其他地儿找win32的实现,找了好久终于找到了。下面对其用法做一个简要说明。
1.首先在下载到了javacomm包后,需要将其解压,解压后需要做的就是将java扩展库安装到本地开发环境以及运行环境中。对于开发环境需要做的就是将win32com.dll复制到%jdk install dir%/bin下,然后将comm.jar和javax.comm.properties拷贝到%jdk install dir%/lib下,对于运行环境要做的就是将这些文件拷贝到相应的jre下即可。
2.javacomm API
其API相当简单,下面看如下代码
CommPortIdentifier serialPortId = CommPortIdentifier.getPortIdentifier(portName);
log.info(”open serial port COM1 …”);
SerialPort port = (SerialPort) serialPortId.open(appName, timeout);
log.info(”serial port COM1 configuration : ” + baudrate + ” , ” + dataBits + ” , ” + stopBits + ” , ” + parity);
port.setSerialPortParams(baudrate, dataBits,stopBits, parity);
port.enableReceiveTimeout(IOTIMEOUT);
OutputStream out = port.getOutputStream();
InputStream in = port.getInputStream();
Request req = Request.getInstance();
req.setIn(in);
req.setOut(out);
第一行取得一个名为portName的串口描述(看这个用法,这个地方有点儿像是单例跟工厂模式)。然后从串口描述中打开串口得到一个串口对象,注意这个地方的timeout参数是用来设置打开串口的超时时间,往后看可以看到还有一个receiveTimeout的设置,这个设置害我冥思苦想了好长时间。一开始没有注意到打开串口时可以设置这个timeout时间,使用的是一个单appName参数的方法,结果后来出现无法设置io超时时间的问题,而java API中也没有提供io超时时间的方法,最后终于一天晚上在给我的她打完电话后发现了这个苦苦期盼了好久的方法,问题迎刃而解了。之后就是设置通信的一些参数诸如波特率,数据位,停止位,校验方式等。然后就可以从串口中得到输入输出流了,这个地方要注意的是串口通信是全双工的,输入流跟输出流相互没有什么关系。
Posted by Wayne Wan in About Work, Reviews on 01-01-2009
上个月碰到一个问题,有一个客户在装了俺们的系统后出现时间错误问题,查了很长时间也没有查到问题所在。后来上google查了下,在sun的网站上查到有人遇到过类似的一个问题,不过那人描述的好像是jdk1.4中的,解决办法就是下载sun出的一个TZupdater的补丁包,它会修正一些时区的问题,可我们的系统用的都是jdk6,应当是不存在这样的问题的。服务器上的时间是正常的北京时间,查看了服务器上的时区设置也是东八区,操作系统是server 2003,按照我的理解jre在默认的情况下应当是去取操作系统的时区的(当然只是猜测),可以查俺们应用的log发现log4j打印出来的日志时间也是错的,跟我们的应用一样时间出现好几个小时的偏差,后来查了下好像我们的应用内用的是北美时区,最后在resin启动的参数中加了 -Dtimezone=asia/shanghai 使得在resin启动的时候就将运行时环境人工设置到asia/shanghai上来,重启resin,问题就解决了。今天又碰到同样的问题,可不同的是我无论怎样设置时区问题依然存在,有点儿搞不明白了,希望在元旦长假过后能顺利解决这个问题。
Posted by Wayne Wan in About Work, Life on 09-12-2008
今天一天过的浑浑噩噩,前几天做了一个怪怪的梦,虽然说我从来认为我是不相信这些东西的,可还是对会产生一种暗示作用,总会有意无意的去联想很多东西出来。有时候想一想自己也一人在外混了这么久了,也没混出个人样。不知道从什么时候起开始对自己很没有信心,做什么事情都表现出一种结果对我无所谓的态度,害怕自己全身心投入后换来却是失败,这种经历有那么一次就已经足够打击一个人一辈子了。有时候会学着阿Q一下,可心底里还是有抹不去的东西。甚至有时候明明将要得到一个东西,看着已经应该是手到擒来的,还是会担心会有意外将这将要得到的所谓的结果带走,真的有点儿像是一朝被蛇咬十年怕井绳。 经常在外面看到一些追逐嬉戏打闹的小孩子,我就会想要是自己在小时候坏一点儿,赖皮一些该多好,至少现在不会因为这些东西所苦恼,至少不会因为背负太高的期望值而被压垮。也许这一切都是自己强加给自己的,何必去在乎那些所谓的七嘴八舌的评价,做好自己就好,可估计没有哪个敢说自己真的能做到不闻窗外事。报纸上整天报道神通,社区里面的老头老太整天议论谁家谁家的儿子多有出息,于是在不同年龄阶段就出现了一个个榜样,榜样的力量是强大的,可也是毁灭性的,导致的结果就是大家都超这个方向去努力,评论一个人的好坏也都会依照榜样的标准,于是上小学的时候就会看你有没有当班长,有没有入少先队,有没有门门功课九十分,上初中就看你有没有考入重点高中,上高中就看你有没有考入名牌大学,大学毕业就又开始看有没有得到一份体面而又多金的工作。在这其中任何一个阶段的失利也许就意味着你不可能按照榜样的标准发展下去了,可还是要以榜样的标准来要求自己甚至强求自己从已经走偏的道路上继续努力回到榜样的路上来,这一切的一切让人觉得人活着真累…… , 也许还是我有些悲观了吧,去除这些杂七杂八的东西能活在这个世上已经是一件很开心的事儿了,有自己爱的人,有爱自己的人,每天可以吃饱穿暖就已经是一件很开心的事情了。 Read the rest of this entry »
Posted by Wayne Wan in About Work on 10-09-2008
1.1. 背景
在应用程序中添加日志记录总的来说基于三个目的:监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析工作;跟踪代码运行时轨迹,作为日后审计的依据;担当集成开发环境中的调试器的作用,向文件或控制台打印代码的调试信息。
最普通的做法就是在代码中嵌入许多的打印语句,这些打印语句可以输出到控制台或文件中,比较好的做法就是构造一个日志操作类来封装此类操作,而不是让一系列的打印语句充斥了代码的主体。
Read the rest of this entry »