文章目录
1 GC是什么?为什么要有GC?
GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。
2 垃圾回收器的基本原理
- 对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。
- 通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是”可达的”,哪些对象是”不可达的”。
- 当GC确定一些对象为”不可达”时,GC就有责任回收这些内存空间。
- 可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。
3 GC算法
3.1 概述
- GC的对象是堆空间和永久区
- GC算法包含:引用计数法,标记清除,标记压缩,复制算法。
3.2 引用计数器
对于一个对象A,只要有任何一个对象引用了A,则A的引用计数器就加1,当引用失效时,引用计数器就减1。只要对象A的引用计数器的值为0,则对象A就不可能再被使用。
3.3 标记清除
- 标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。
- 在标记阶段,首先通过根节点,标记所有从根节点开始的可达对象。因此,未被标记的对象就是未被引用的垃圾对象。
- 然后,在清除阶段,清除所有未被标记的对象。
3.4 复制算法
复制算法是一种相对高效的回收方法不适用于存活对象较多的场合如老年代将原有的内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。
3 垃圾回收的优点以及原理
由于有个垃圾回收机制,Java中的对象不再有"作用域"的概念,只有对象的引用才有"作用域"。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。
4 内存泄漏
4.1 什么是内存泄漏
Java中的内存泄露,广义并通俗的说,就是:不再会被使用的对象的内存不能被回收,就是内存泄露。
4.2 内存泄漏原因
如果长生命周期的对象持有短生命周期的引用,就很可能会出现内存泄露。
- 非必要的对象引用
- 未释放的系统资源
4.3 非必要的对象引用
Java代码常常保留对于不再需要的对象引用, 并且这组织了内存的垃圾收集器的工作. Java对象通常被其他对象包含引用, 为此一个单一对象可以保持整个对象树在内存中, 于是导致了如下问题:
- 在向数组添加对象以后遗漏了对于他们的处理,直到你再次使用对象的时候都不释放引用(比如一个菜单指令可以插件一个对象实例引用并且不释放便于以后再次调用的时候使用, 但是也许永远不会发生)
- 在其他引用依然需要旧有状态的时候贸然修改对象状态。(比如当你为了在一个文本文件里面保存一些属性而使用一个数组, 诸如”字符个数”等字段在不再需要的时候依然保留在内存当中)
- 允许一个长久执行的线程所引用的对象. 设置引用为NULL也无济于事, 在线程退出和空闲之前, 对象不会被收集释放
4.4 未释放的系统资源
Java方法可以定位Java实例意外的堆内存, 诸如针对视窗和位图的内存资源. Java常常通过JNI(Java Native Interface)调用C/C++子程序定位这些资源.