最近的一个项目应用了Acegi作为安全框架,项目试运行期间出现了一个隐藏比较深的Bug:当运行一段时间之后,对于URL资源串的控制功能失效!在更新了acegi最新版本后仍没有排除该Bug。
因为该Bug的发生需要在运行一段时间后才会发现,排查起来比较困难,因此需要通过测试工具进行一定时间的压力测试以后来重现故障的发生!
在 通过压力测试排查Bug(一)--测试过程 中我把测试的步骤介绍了一下,下面我将该Bug的排查过程介绍一下,以供参考:
通过MyEclipse的调试模式运行的Web应用程序,可以通过设置断点进行单步调试,设置断点很容易,只需要在代码行之前(行数标注上)双击鼠标左键即可。当程序运行该代码处即会暂停运行,你可以在Debug模式窗口中观察程序运行状态。
因为acegi对url的控制是在filter中进行的,所以我将断点设置在了继承了AbstractFilterInvocationDefinitionSource的自定义filter中:
通过观察断点处的变量值,发现urls变量的值不正常,该值应该是在后台管理的所有URL资源才对,现在全部变成了多个一样的同一个URL,问题就出在了这里!什么导致了变量值的紊乱呢?以下方法引起了我的注意:
//倒叙排序所有获取的url orderUrls(urls);
/** * 把url资源按倒序排序 * @param urls */ private void orderUrls(List<String> urls) { Collections.sort(urls); Collections.reverse(urls); }
该方法对urls按照字母顺序进行了倒序排序,因为Collections.sort是静态方法,在执行时,值参应该是在一处内存地址上操作,因此并发操作时,一定会产生互相干扰重叠的排序操作,造成了urls变量值的紊乱!
因此我将该方法前加上了synchronized关键字,防止多个线程同时访问这个方法。
/** * 把url资源按倒序排序 * @param urls */ private synchronized void orderUrls(List<String> urls) { Collections.sort(urls); Collections.reverse(urls); }
再经过一轮的压力测试,没有再出现类似的问题,至此该Bug成功消除!
出现的这个缺陷提醒我们,以后编程时一定要注意线程并发操作的影响,在有影响的位置注意使用synchronized 关键字来防止多个线程同时访问一处代码!
同时看出,压力测试的必要性,不进行适当的压力测试有可能发现不了更隐蔽的缺陷,尤其是多线程并发操作的应用。压力测试还能考察开发出来的系统的性能如何、运行是否稳定、是否能够满足实际应用环境的客户的访问量。