图片加载<第三篇>:垃圾回收机制

(1)垃圾回收机制的意义

java 语言中一个显著的特点就是引入了java回收机制,是c++程序员最头疼的内存管理的问题迎刃而解,它使得java程序员在编写程序的时候不在考虑内存管理。由于有个垃圾回收机制,java中的额对象不在有“作用域”的概念,只有对象的引用才有“作用域”。垃圾回收可以有效的防止内存泄露,有效的使用空闲的内存;

说到这,不得不提起内存泄漏(memory leak)和内存溢出(out of memory)

(2)内存泄漏内存溢出

内存泄漏: 是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。

内存溢出: 指程序申请内存时,没有足够的内存供申请者使用,或者说,给了你一块存储int类型数据的存储空间,但是你却存储long类型的数据,那么结果就是内存不够用,此时就会报错OOM,即所谓的内存溢出。

内存泄露量大到一定程度会导致内存溢出。但是内存溢出不一定是内存泄露引起的。

(3)内存泄漏的分类(按发生方式来分类)

常发性内存泄漏: 发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。
偶发性内存泄漏: 发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。
一次性内存泄漏: 发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。
隐式内存泄漏: 程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏

(4)内存溢出原因
  1. 内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
  2. 集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
  3. 代码中存在死循环或循环产生过多重复的对象实体;
  4. 使用的第三方软件中的BUG;
  5. 启动参数内存值设定的过小;
(5)GC

Android触发垃圾回收机制的时机是无法确定的,但是可以执行

            System.gc();

主动触发垃圾回收机制。

(6)Android代码中的堆和栈

了解垃圾回收机制,必须了解堆和栈的关系,上面是我用画图工具画的简单图。

首先我画了两个矩形区域,一个代表栈空间(负责存储对象的引用),一个代表堆空间(负责存储对象的实例),c是一个引用,存入栈空间,new Object()是对象,存入堆空间,两者存在引用关系,用一根直线来表示。

重点知识: 因为存在引用关系,所以垃圾回收机制是无法回收这个对象的。

当执行以下代码时,引用将会断掉

c = null;

这时,下次垃圾回收机制触发时,Object的实例会被回收。

由于引用存入栈空间占用空间很小,对象存入堆中占用空间很大,所以将堆中无引用的对象回收是垃圾回收机制的主要工作。

那么,是否只要执行了c = null;,垃圾回收机制就一定会将对象回收呢?

答案是不一定。我再画一个简单图来说明:

这是一个 简单的树形结构,GC Roots是垃圾回收机制树形结构的根节点,当对象存在引用时,我们就在GC Roots和对象之间画一条直线,如果设置为null

a = null;

GC Roots和a的连线就会断开,如图:

这种情况下,当垃圾回收机制触发时,由于a对象和b对象也存在引用关系,所以对象a不会被回收,这样就造成了内存泄漏。

(7)原理

本来想画个图来说一下垃圾回收机制的原理的,后来发现图画的并不咋滴,然后我查找了很多很多有关垃圾回收机制的文章,最后终于找到一篇和我脑海中的图差不多的,Java 技术之垃圾回收机制,这篇文章写得非常不错,只能用牛逼来形容,我也认真读完了,大家看一下这篇文章的这张图

顶端有一个节点是GC Roots,这是垃圾回收机制树形结构的根节点,其中object 1、object 2、object 3、object 4和GC Roots存在直接或者间接的引用,object 5、object 6、object 7和GC Roots不存在引用,那么可以总结为:

  • object 1、object 2、object 3、object 4与根节点仍然存在引用;
  • object 5、object 6、object 7与根节点不存在引用,所以可以被GC回收。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章