移动端测试=== 两个概念 内存泄漏 和 内存溢出 【转】

关于内存在一块其实我并非很想拿出来讲,通常状况下内存这一块都是可优化的,能够经过硬件资源或者调整一些系统或者应用系统的参数配置来进行优化。html

  不少同僚问到了“内存泄漏”和“内存溢出”,其实这个在baidu上就有解释。而咱们不少人常常会混淆了这两个东西,在这里我就简单的引用一些资源说一下他们。
   内存泄漏
  内存泄漏也称做“存储渗漏”,用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果致使一直占据该内存单元。直到程序结束。(其实说白了就是该内存空间使用完毕以后未回收)即所谓内存泄漏。
  内存泄漏形象的比喻是“ 操做系统可提供给全部进程的存储空间正在被某个进程榨干”,最终结果是程序运行时间越长,占用存储空间愈来愈多,最终用尽所有存储空间,整个系统崩溃。因此“内存泄漏”是从操做系统的角度来看的。这里的存储空间并非指物理内存,而是指虚拟内存大小,这个虚拟内存大小取决于磁盘交换区设定的大小。由程序申请的一块内存,若是没有任何一个指针指向它,那么这块内存就泄漏。
   表象
   性能测试的时候发生内存泄漏的表象就是可用内存逐渐减小,一直不释放。
   内存泄漏分类
  以发生的方式来分类,内存泄漏能够分为4类
   常发性
  发生内存泄漏的代码会被屡次执行到,每次被执行的时候都会致使一块内存泄漏。
   偶发性
  发生内存泄漏的代码只有在某些特定环境或操做过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。因此测试环境和测试方法对检测内存泄漏相当重要。
   一次性
  发生内存泄漏的代码只会被执行一次,或者因为算法上的缺陷,致使总会有一块且仅一块内存发生泄漏。好比,在类的构造函数中分配内存,在析构函数中却没有释放该内存,因此内存泄漏只会发生一次。
   隐式
  程序在运行过程当中不停的分配内存,可是直到结束的时候才释放内存。严格的说这里并无发生内存泄漏,由于最终程序释放了全部申请的内存。可是对于一个服务器程序,须要运行几天、几周甚至几个月,不及时释放内存也可能致使最终耗尽系统的全部内存。因此,咱们称这类内存泄漏为隐式内存泄漏。
   危害
  内存泄漏或者是说,资源耗尽后,系统会表现出什么现象啊?
  cpu资源耗尽:估计是机器没有反应了,键盘,鼠标,以及网络等等。在中了计算机病毒的设备上很是常见。
  进程id耗尽:无法建立新的进程了,串口或者telnet都无法建立了。
  硬盘耗尽: 机器要死了,交换内存无法用,日志也无法用了,死是很正常的。
  内存泄漏或者内存耗尽:新的链接没法建立,free的内存比较少。发生内存泄漏的程序不少,可是要想产生必定的后果,就须要这个进程是无限循环的,是个服务进程。固然,内核也是无限循环的,因此,若是内核发生了内存泄漏,状况就更加不妙。内存泄漏是一种很难定位和跟踪的错误,目前还没看到有什么好用的工具(固然,用户空间有一些工具,有静态分析的,也会动态分析的,可是找内核的内存泄漏,没有好的开源工具)。
  内存泄漏和对象的引用计数有很大的关系,再加上c/c++都没有自动的垃圾回收机制,若是没有手动释放内存,问题就会出现。若是要避免这个问题,仍是要从代码上入手,良好的编码习惯和规范,是避免错误的不二法门。
  通常咱们常说的内存泄漏是指堆内存的泄漏。
  堆内存是指程序从堆中分配的,大小任意的(内存块的大小能够在程序运行期决定),使用完后必须显式释放的内存。
  应用程序通常使用malloc,realloc,new等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用free或delete释放该内存块,不然,这块内存就不能被再次使用,咱们就说这块内存泄漏了。
   部分检测工具
  1.ccmalloc- Linux和Solaris下对C和C++程序的简单的使用内存泄漏和malloc调试库。
  2.Dmalloc-Debug Malloc Library.
  3.Electric Fence-Linux分发版中由Bruce Perens编写的malloc()调试库。
  4.Leaky-Linux下检测内存泄漏的程序。
  5.LeakTracer-Linux、Solaris和HP-UX下跟踪和分析C++程序中的内存泄漏。
  6.MEMWATCH-由Johan Lindh编写,是一个开放源代码C语言内存错误检测工具,主要是经过gcc的precessor来进行。
  7.Valgrind-Debugging and profiling Linux programs, aiming at programs written in C and C++.
  8.KCachegrind-A visualization tool for the profiling data generated by Cachegrind and Calltree.
  9.IBM Rational PurifyPlus-帮助开发人员查明C/C++、托管.NET、Java和VB6代码中的性能和可靠性错误。PurifyPlus 将内存错误和泄漏检测、应用程序性能描述、代码覆盖分析等功能组合在一个单1、完整的工具包中。
  10.ParasoftInsure++-针对C/C++应用的运行时错误自动检测工具,它可以自动监测C/C++程序,发现其中存在着的内存破坏、内存泄漏、指针错误和I/O等错误。并经过使用一系列独特的 技术(SCI技术和变异测试等),完全的检查和测试咱们的代码,精肯定位错误的准确位置并给出详细的诊断信息。能做为MicrosoftVisual C++的一个插件运行。
  11.Compuware DevPartner for Visual C++ BoundsChecker Suite-为C++开发者设计的运行错误检测和调试工具软件。做为Microsoft Visual Studio和C++ 6.0的一个插件运行。
  12.Electric Software GlowCode-包括内存泄漏检查,code profiler,函数调用跟踪等功能。给C++和.Net开发者提供完整的错误诊断,和运行时性能分析工具包。
  13.Compuware DevPartner Java Edition-包含Java内存检测,代码覆盖率测试,代码性能测试,线程死锁,分布式应用等几大功能模块。
  14.Quest JProbe-分析Java的内存泄漏。
  15.ej-technologies JProfiler-一个全功能的Java剖析工具,专用于分析J2SE和J2EE应用程序。它把CPU、执行绪和内存的剖析组合在一个强大的应用中。
  16.BEAJRockit-用来诊断Java内存泄漏并指出根本缘由,专门针对Intel平台并获得优化,能在Intel硬件上得到最高的性能。
   内存溢出
  (out of memory)通俗理解就是内存不够,一般在运行大型软件或游戏时,软件或游戏所须要的内存远远超出了你主机内安装的内存所承受大小,就叫内存溢出。此时软件或游戏就运行不了,系统会提示内存溢出,有时候会自动关闭软件,重启电脑或者软件后释放掉一部份内存又能够正常运行该软件或游戏一段时间。
   表象
  常见out of memory 错误
   产生缘由
  内存溢出是指应用系统中存在没法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于虚拟机能提供的最大内存。为了解决Java中内存溢出问题,咱们首先必须了解Java是如何管理内存的。Java的内存管理就是对象的分配和释放问题。在Java中,内存的分配是由程序完成的,而内存的释放是由垃圾收集器(GarbageCollection,GC)完成的,程序员不须要经过调用GC函数来释放内存,由于不一样的JVM实现者可能使用不一样的算法管理GC,有的是内存使用到达必定程度时,GC才开始工做,也有定时执行的,有的是中断式执行GC。但GC只能回收无用而且再也不被其它对象引用的那些对象所占用的空间。Java的内存垃圾回收机制是从程序的主要运行对象开始检查引用链,当遍历一遍后发现没有被引用的孤立对象就做为垃圾回收。
  引发内存溢出的缘由有不少种,常见的有如下几种:
  (1)内存中加载的数据量过于庞大,如一次从 数据库取出过多数据;
  (2)集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
  (3)代码中存在死循环或循环产生过多重复的对象实体;
  (4)使用的第三方软件中的BUG;
  (5)启动参数设定的太小;
   解决方法
  内存溢出虽然很棘手,但也有相应的解决办法,能够按照从易到难,一步步的解决。
  第一步,就是修改JVM启动参数,直接增长内存。这一点看上去彷佛很简单,但很容易被忽略。JVM默承认以使用的内存为64M,Tomcat默承认以使用的内存为128MB,对于稍复杂一点的系统就会不够用。在某项目中,就由于启动参数使用的默认值,常常报“OutOfMemory”错误。所以,-Xms,-Xmx参数必定不要忘记加。
  第二步,检查错误日志,查看“OutOfMemory”错误前是否有其它异常或错误。在一个项目中,使用两个数据库链接,其中专用于发送 短信的数据库链接使用DBCP链接池管理,用户为不将短信发出,有意将数据库链接用户名改错,使得日志中有许多数据库链接异常的日志,一段时间后,就出现“OutOfMemory”错误。经分析,这是因为DBCP链接池BUG引发的,数据库链接不上后,没有将链接释放,最终使得DBCP报“OutOfMemory”错误。通过修改正确数据库链接参数后,就没有再出现内存溢出的错误。
  查看日志对于分析内存溢出是很是重要的,经过仔细查看日志,分析内存溢出前作过哪些操做,能够大体定位有问题的模块。
  第三步,安排有经验的编程人员对代码进行走查和分析,找出可能发生内存溢出的位置。重点排查如下几点:
  (1) 检查代码中是否有死循环或递归调用。
  (2) 检查是否有大循环重复产生新对象实体。
  (3) 检查对数据库查询中,是否有一次得到所有数据的查询。通常来讲,若是一次取十万条记录到内存,就可能引发内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引发内存溢出。所以对于数据库查询尽可能采用分页的方式查询。
  (4) 检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。
  第四步,使用内存查看工具动态查看内存使用状况。某个项目上线后,每次系统启动两天后,就会出现内存溢出的错误。这种状况通常是代码中出现了缓慢的内存泄漏,用上面三个步骤解决不了,这就须要使用内存查看工具了。
  内存查看工具备许多,比较有名的有:Optimizeit Profiler、JProbeProfiler、JinSight和Java1.5的Jconsole等。它们的基本工做原理大同小异,都是监测Java程序运行时全部对象的申请、释放等动做,将内存管理的全部
  信息进行统计、分析、可视化。开发人员能够根据这些信息判断程序是否有内存泄漏问题。通常来讲,一个正常的系统在其启动完成后其内存的占用量是基本稳定的,而不该该是无限制的增加的。持续地观察系统运行时使用的内存的大小,能够看到在内存使用监控窗口中是基本规则的锯齿形的图线,若是内存的大小持续地增加,则说明系统存在内存泄漏问题。经过间隔一段时间取一次内存快照,而后对内存快照中对象的使用与引用等信息进行比对与分析,能够找出是哪一个类的对象在泄漏。
  经过以上四个步骤的分析与处理,基本能处理内存溢出的问题。固然,在这些过程当中也须要至关的经验与敏感度,须要在实际的开发与调试过程当中不断积累。
   缓冲区溢出
  为了便于理解,咱们不妨打个比方。缓冲区溢出比如是将十磅的糖放进一个只能装五磅的容器里。一旦该容器放满了,余下的部分就溢出在柜台和地板上,弄得一团糟。因为计算机程序的编写者写了一些编码,可是这些编码没有对目的区域或缓冲区——五磅的容器——作适当的检查,看它们是否够大,可否彻底装入新的内容——十磅的糖,结果可能形成缓冲区溢出的产生。若是打算被放进新地方的数据不适合,溢获得处都是,该数据也会制造不少麻烦。可是,若是缓冲区仅仅溢出,这只是一个问题。到此时为止,它尚未破坏性。当糖溢出时,柜台被盖住。能够把糖擦掉或用吸尘器吸走,还柜台原本面貌。与之相对的是,当缓冲区溢出时,过剩的信息覆盖的是计算机内存中之前的内容。除非这些被覆盖的内容被保存或可以恢复,不然就会永远丢失。
  在丢失的信息里有可以被程序调用的子程序的列表信息,直到缓冲区溢出发生。另外,给那些子程序的信息——参数——也丢失了。这意味着程序不能获得足够的信息从子程序返回,以完成它的任务。就像一我的步行穿过沙漠。若是他依赖于他的足迹走回头路,当沙暴来袭抹去了这些痕迹时,他将迷失在沙漠中。这个问题比程序仅仅迷失方向严重多了。入侵者用精心编写的入侵代码(一种恶意程序)使缓冲区溢出,而后告诉程序依据预设的方法处理缓冲区,而且执行。此时的程序已经彻底被入侵者操纵了。
  入侵者常常改编现有的应用程序运行不一样的程序。例如,一个入侵者能启动一个新的程序,发送秘密文件(支票本记录,口令文件,或财产清单)给入侵者的电子邮件。这就好像不只仅是沙暴吹了脚印,并且后来者也会踩出新的脚印,将咱们的迷路者领向不一样的地方,他本身一无所知的地方。
   缓冲处理
  你屋子里的门和窗户越少,入侵者进入的方式就越少……
  因为缓冲区溢出是一个编程问题,因此只能经过修复被破坏的程序的代码而解决问题。若是你没有源代码,从上面“堆栈溢出攻击”的原理能够看出,要防止此类攻击,咱们能够:
  一、开放程序时仔细检查溢出状况,不容许数据溢出缓冲区。因为编程和编程语言的缘由,这很是困难,并且不适合大量已经在使用的程序;
  二、使用检查堆栈溢出的编译器或者在程序中加入某些记号,以便程序运行时确认禁止 黑客有意形成的溢出。问题是没法针对已有程序,对新程序来说,须要修改编译器;
  三、常常检查你的操做系统和应用程序提供商的站点,一旦发现他们提供的补丁程序,就立刻下载而且应用在系统上,这是最好的方法。可是系统管理员总要比攻击者慢一步,若是这个有问题的软件是可选的,甚至是临时的,把它从你的系统中删除。举另一个例子,你屋子里的门和窗户越少,入侵者进入的方式就越少。
  扯远了,这些是安全性测试方面的内容。不过性能测试方面有时候也得注意这些内容。性能测试的时候若是应用程序不报错,而且系统的可用内存不是在不断减小,就能够认为内存正常。
 
 
 
 
 
本文转自: http://www.51testing.com/html/80/n-3721680.html
相关文章
相关标签/搜索