垃圾回收机制garbage collection
内存管理
Java的内存管理一般指对象管理,包括:
对象空间的分配:new关键字创建对象。
对象空间的释放:将对象赋值null即可。
垃圾回收器作用:发现无用对象【没有任何变量引用该对象】并将其占用的内存空间回收。
垃圾回收算法
1.引用计数法
堆内存中每个对象被引用一次,计数加一,引用变量变为null,则计数减一,直至计数为0变为空变为无用对象。
优点:算法简单。
缺点:循环引用的无用对象无法识别。
示例:
2.引用可达法(根搜索算法)
把所有引用关系看作一张图,从一个根节点GC ROOT出发,寻找对应的引用节点以及其节点的引用节点,当整个寻找流程完毕,剩余没有找到(引用)的节点就是无用的对象。
分代垃圾回收机制
原因:不同对象的生命周期不一致,要分别采用不同的回收算法,提高回收效率。
对象分为三种状态:年轻代、年老代、持久代。JVM堆内存中分为Eden、Survivor和 Tenured/Old 空间。年轻代(Eden,Survivor),年老代(Tenured/Old)。
对象状态
1. 年轻代
存放:所有新生成的对象首放位置。
目标:尽可能快速收集掉那些生命周期短的对象,对应的是Minor GC。
概述:Minor GC采用效率较高的复制算法、频繁的操作清理年轻代内存,但是会浪费内存空间。年轻代区域存放满对象后,就将对象存放到年老代区域。
Eden存放:从未通过垃圾回收的新对象。
Survivor存放:垃圾回收(小于15次)后仍然有用的对象,循环存放。
2. 年老代
存放:一些生命周期较长的对象,年轻代中经历了n(默认15)次垃圾回收后仍然存活的对象。每次经过回收存活下来的对象年龄会加1。老年代中启动GC的频率较低,回收的效率也比较低。
概述:当对象装满Old区,会同时启动Major GC和Full GC(全量回收)全面清理年轻代区域和年老代区域。
3. 持久代
存放静态文件,如Java类、方法等(类信息、常量、静态变量、即时编译器编译后的代码)。持久代对垃圾回收没有显著影响。
回收器介绍
Minor GC:
作用:清理年轻代。
概述:Eden区满了就会触发一次Minor GC。清理无用对象,将有用对象复制到“Survivor1”、“Survivor2”区(两个区大小空间也相同,同一时刻Survivor1和Survivor2只有一个在用,一个为空)。
Major GC:
作用:清理年老代区域。
Full GC:
作用:清理年轻代、年老代区域。
概述:成本较高,会影响性能。性能优化主要是优化Full GC。
垃圾回收过程分析
1.绝大多数新对象放在Eden区。
2.满了之后【不能创造对象】调用Minor GC清理无用对象,把有用对象放到survivor1或者survivor2,假如放在survivor1,同时把Eden清空。
3.当Eden再次满之后。先在survivor1调用Minor GC清理无用对象,把有用对象放到survivor2,。同时在Eden调用Minor GC清理无用对象,把有用对象放到survivor,清空Eden。
4.当survivor区域循环存放超过15次之后调用Minor GC把仍然有用的对象存放在Old区。
5.当Old区的对象达到一定的比例会启动Major GC清理一下。
6.当Old区满之后调用Full GC清理年轻代和年老代区域(包括Eden、Survivor、Old)。
Full GC被调用的时机
年老代区写满
持久代区写满
程序里写System.gc(),不建议使用,系统自己知道调用。
一次GC后Heap堆各域分配策略动态变化。
开发中容易造成内存泄露(系统奔溃)的操作
暂时不讲,很多知识要后面才学到,等工作中用到再回头看。
创建大量无用对象:比如使用String而非StringBuilder拼接大量拼接字符串。
2 静态集合类的使用:如HashMap、Vector、List,静态变量的生命周期和应用程序一致导致所有对象Object不能被释放。
3 各种连接对象(IO流对象、数据库连接对象、网络连接对象)未关闭,这些连接对象属于物理连接,不使用的时候请及时关闭。(开发中不关闭运行经常会出现bug,一定要注意)
4 监听器的使用:释放对象时没有删除相应监听器。
要点:
1 程序员无权调用垃圾回收器。
2 调用System.gc()只是通知JVM,并非运行垃圾回收器,而且会启动Full GC,影响系统性能(前面章节有讲,请仔细看)。
3 finalize()是释放对象或资源的方法,建议少用。
Last updated
Was this helpful?