本文链接:https://blog.csdn.net/jie1175623465/article/details/81121548
内存泄漏(memory leak):
是指程序在申请内存后,无法释放已申请的内存空间就造成了内存泄漏,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。
内存泄漏的例子:
Vector v = new Vector( 10 );
for ( int i = 1 ;i < 100 ; i ++ ){
Object o = new Object();
v.add(o);
o = null ;
}
在这个例子中,代码栈中存在Vector 对象的引用 v 和 Object 对象的引用 o 。
在 For 循环中,我们不断的生成新的对象,然后将其添加到 Vector 对象中,之后将 o 引用置空。问题是当 o 引用被置空后,
如果发生 GC ,
我们创建的 Object 对象是否能够被 GC 回收呢?
答案是否定的。
因为, GC 在跟踪代码栈中的引用时,
会发现 v 引用,而继续往下跟踪,就会发现 v 引用指向的内存空间中又存在指向 Object 对象的引用。也就是说尽管 o 引用已经被置空,
但是 Object 对象仍然存在其他的引用,是可以被访问到的,所以 GC 无法将其释放掉。
如果在此循环之后, Object 对象对程序已经没有任何作用,
那么我们就认为此 Java 程序发生了内存泄漏。
内存溢出(out of memory):
指程序申请内存是,没有足够的内存供申请者使用,或者说,给你一块存储int类型的数据存储空间,但你却存long类型的数据,那么结果就是内存不够用,此时就会报OOM,即所谓的内存溢出,简单来说就是自己所需要的空间比我们所拥有的内存大内存不够使用所造成的内存溢出。
比方说:一个停车场(堆)保安(gc)让很久不用的废弃车子(无用对象)从车位移走。但这个车子又没办法挪走,这就是内存泄漏。停车场的车位都有车子占用,再来车子就没地了,或者给你一个小汽车的车位(int)你非要停一辆高铁(long);即所谓的内存溢出。
内存泄漏的分类(按发生方式来分类)
1.常发性内存泄漏:发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。
2.偶发性内存泄漏:发生内存泄漏的代码只是在某些特定环境或操作过程中才发生的。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。
3.一次性内存泄漏:发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块且仅一块内存发生泄漏。比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。
4.隐士内存泄漏:程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。
内存泄漏的解决方法:
1.内存泄漏也许是因为活动已经被使用完毕,但是仍然在其他地方被引用,导致无法对其进行回收。我们只需要给对活动进行引用的类独立出来或者将其变为静态类,该类水质活动的结束而结束,也就没有了当活动结束但仍然还是被其他类引用的情况。
2.资源性对象在不使用的时候,应该调用它的close()函数将其关闭掉。。。
3.集合容器中的内存泄漏,我们通常把一些对们通常把一些对象的引用加入到了集合容器(比如ArrayList)中,当我们不需要该对象时,并没有把它的引用从集合中清理掉,这样这个集合就会越来越大。如果这个集合是static的话,那情况就更严重了。
需要在退出程序之前,将集合里的东西clear,然后置为null,再退出程序。
WebView造成的泄露,当我们不使用WebView对象时,应该调用它的destory()函数来销毁它,并释放其占用的内存,否则其长期占用的内存也不能被回收,从而造成内存泄露。
我们应该为WebView另外开启一个进程,通过AIDL与主线程进行通信,WebView所在的进程可以根据业务的需要选择合适的时机进行销毁,从而达到内存的完整释放。
内存溢出的原因及解决方法:
1.内存溢出的原因:
(1)内存中加载的数据量过于庞大,如一次从数据库取出过多数据。
(2)集合类中有对对象的引用,使用完后未清空,产生堆积,使得JVM不能回收;
(3)代码中存在死循环或者循环产生过得重复的对象实体;
(4)使用的第三方软件中的BUG;
(5)启动参数内存值设定的过小;
2.内存溢出的解决方案:
第一步:修改JVM启动参数,直接增加内存。(-Xms,-Xmx参数一定不要忘记加。)
第二步:检查错误日志,查看"OutOfMemory"错误前是否有其他异常或错误。
第三步:对代码进行走查和分析,找出可能产生内存溢出的位置。