最近的一个项目,采用JSP+Servlet开发的Web应用,功能不复杂,涉及到一些多线程处理及网络编程。测试期间发现在会造成系统时钟变快,基本运行不到一小时就快了10来分钟,开出时钟程序能明显感觉秒钟跳动比较快。检查过代码没有用到任何有关时间设置的调用,JVM、TOMCAT也换过多个版本,依然没能解决问题。由于我们的项目程序不运行时系统时钟一切正常,启动后立刻变快,初步硬件或是其他程序造成的问题。另外,最奇怪的是并不是所有机器上运行都有这种问题,公司里的3台2003Server上,2台有此现象,另一台始终正常,开发用的一些xp/vista的机器也不都存在这个问题。
着实郁闷了很长一段时间,始终找不到问题的关键,更没法找到解决办法。前两天偶然查到一篇SUN网站bug库中早些年的一篇文章:(ID:4500388)Calling Thread.sleep with small argument affects system clock on windows ,其中说明了当多线程处理时,调用Thread.sleep()方法时,若sleep的参数小于10ms就可能会造成windows系统时钟变快。不过该bug标记为jvm 1.3中才存在,并且已经在后续版本fixed,而我们开发都是用的1.6版本。于是搜索了下项目代码,确实有用到Thread.sleep()方法的地方,而且某些部分由于需求关系,程序中的参数不定的,会依据一定算法计算出来,这样就有可能小于10ms,尽管理论上我们代码中可能最小只设定到50ms左右。
接下来继续搜了下其他的bug report,包括ID为5005837 、6435126的文章,发现上述问题并未根本解决。根据文章中提到的ForceTimeHighResolution关键字google一下,发现这个参数是JVM 中的一个;另外搜到老外的帖子里有一篇关于applet游戏程序时钟走快后,其厂商给出的解决办法,就是需要开启ForceTimeHighResolution参数!
这下好了,这应该就是解决问题的关键所在。重新将项目服务器时间校准,然后在TOMCAT的catalina.bat中将JAVA_OPTS参数中增加一项 -XX:+ForceTimeHighResolution (注意 - 和 + 都是有的),启动TOMCAT运行。查看时钟,感觉没有变快,运行1小时后,未发现变快现象,看来这个参数确实很有效。剩下工作就是把所有安装项目程序的服务器都修改了参数设置,进行长时间运行测试,直至目前为止,均未在出现时钟变快的现象。
经过这件事后,确实没想到JVM还有这样的BUG。以前C#的代码写的多,接触JAVA时间不太长,这次算是见识到了JAVA中千奇百怪的问题了。不过至于程序中开启了ForceTimeHighResolution这个参数会不会带来别方面问题,还无从得知,只有待时间来检验了。如果这方面有了解的朋友欢迎与我交流。