扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
1 问题的提出
笔者曾经参与开发的网管系统,系统规模庞大,涉及上百万行代码。系统主要采用Java语言开发,大体上分为客户端、服务器和数据库三个层次。在版本进入测试和试用的过程中,现场人员和测试部人员纷纷反映:系统的稳定性比较差,经常会出现服务器端运行一昼夜就死机的现象,客户端跑死的现象也比较频繁地发生。对于网管系统来讲,经常性的服务器死机是个比较严重的问题,因为频繁的死机不仅可能导致前后台数据不一致,发生错误,更会引起用户的不满,降低客户的信任度。因此,服务器端的稳定性问题必须尽快解决。
2 解决思路
通过察看服务器端日志,发现死机前服务器端频繁抛出OutOfMemoryException内存溢出错误,因此初步把死机的原因定位为内存泄漏引起内存不足,进而引起内存溢出错误。如何查找引起内存泄漏的原因呢?有两种思路:第一种,安排有经验的编程人员对代码进行走查和分析,找出内存泄漏发生的位置;第二种,使用专门的内存泄漏测试工具Optimizeit进行测试。这两种方法都是解决系统稳定性问题的有效手段,使用内存测试工具对于已经暴露出来的内存泄漏问题的定位和解决非常有效;但是软件测试的理论也告诉我们,系统中永远存在一些没有暴露出来的问题,而且,系统的稳定性问题也不仅仅只是内存泄漏的问题,代码走查是提高系统的整体代码质量乃至解决潜在问题的有效手段。基于这样的考虑,我们的内存稳定性工作决定采用代码走查结合测试工具的使用,双管齐下,争取比较彻底地解决系统的稳定性问题。
在代码走查的工作中,安排了对系统业务和开发语言工具比较熟悉的开发人员对应用的代码进行了交叉走查,找出代码中存在的数据库连接声明和结果集未关闭、代码冗余和低效等故障若干,取得了良好的效果,文中主要讲述结合工具的使用对已经出现的内存泄漏问题的定位方法。
3 内存泄漏的基本原理
在C++语言程序中,使用new操作符创建的对象,在使用完毕后应该通过delete操作符显示地释放,否则,这些对象将占用堆空间,永远没有办法得到回收,从而引起内存空间的泄漏。如下的简单代码就可以引起内存的泄漏:
|
在function()方法执行完毕后,vec数组已经是不可达对象,在C++语言中,这样的对象永远也得不到释放,称这种现象为内存泄漏。
而Java是通过垃圾收集器(Garbage Collection,GC)自动管理内存的回收,程序员不需要通过调用函数来释放内存,但它只能回收无用并且不再被其它对象引用的那些对象所占用的空间。在下面的代码中,循环申请Object对象,并将所申请的对象放入一个Vector中,如果仅仅释放对象本身,但是因为Vector仍然引用该对象,所以这个对象对GC来说是不可回收的。因此,如果对象加入到Vector后,还必须从Vector中删除,最简单的方法就是将Vector对象设置为null。
|
实际上无用,而还被引用的对象,GC就无能为力了(事实上GC认为它还有用),这一点是导致内存泄漏最重要的原因。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者