一、垃圾回收过程
- 发现无用的对象
- 回收无用的对象占用的内存空间
二、相关算法
1.引用计数法
堆中的每一个对象都有一个引用计数。被引用一次,计数加1,被引用变量值变为null,计数减1,当计数为0是,则被视为无用对象。算法简单,但是循环引用的无用对象无法识别。
2.引用可达法(根搜索算法)
程序把所有引用关系看做一张图,从一些节点GC Roots开始,寻找这些节点对应的引用节点,找到节点后,继续寻找这个节点对应的引用节点,当所有的引用节点寻找完毕后,剩余没有被引用到的节点(即当一个对象到GC Roots没有任何引用链时),就是无用对象。
三、垃圾回收机制
1.对象的三种状态
(1)年轻代(Eden区、Survivor区)
新生成的对象放在Eden区,对应的回收是Minor GC。
(2)年老代(Tenured/Old区)
在年轻代中经历了N(默认15)次垃圾回收的对象,会进入老年代,放在Tenured/Old区,对应的回收器是Major GC和Full GC。
(3)持久代(方法区)
用于存放静态文件,如Java类、方法等,放在静态方法区,不会被回收。
四、垃圾回收过程
- 新创建的对象,绝大多数都存放在Eden区中。
- Eden区满了或达到一定比例时,就会出发Minor GC,清理Eden区和Survivor区中的无用对象,将有用的对象复制到Survivor1或Survivor2中(这两个区大小相同,同一时刻一个在用,一个为空),同时清空Eden区。
- 重复2的动作(默认15次)在Survivor区中依然存在的对象,则复制到Old(Tenured)区。
- 当Old(Tenured)区满了,则会触发Full GC,全面清理年轻代和年老代所在的区域,很耗资源。
五、开发中的内存泄漏
- 创建大量无用对象,比如拼接字符串时,用“String+”,不用StringBuilder。
- 静态集合类的使用,如static HashMap、static Vetor、static List,这些静态变量的生命周期和引用程序一致,不会被释放。
- 各种连接对象,如IO流、数据库连接、网络连接未关闭,这些是物理连接需要手动关闭,GC无能为力。
- 监听器的使用,释放对象时,没有删除相应的监听器。