一、垃圾回收的意义:
在Java中,当没有对象引用指向原先分配给某个对象时,该内存便成为垃圾。实际上,除了释放没用的对象,垃圾回收也可以清除内存记录碎片。垃圾回收能自动的释放内存空间,减轻编程的负担,这Java虚拟机具有一些优点,首先,它能使编程效率提高。在没有回收机制的视乎,可能要花费许多时间来解决一个难懂的存储问题。在Java编程中,靠垃圾回收机制可大大缩短时间,其次是它保存程序的完整性,垃圾回收是Java语言安全策略的重要部分。
二、如何确定一个对象是否可以被收回?
1.引用计数算法
是通过判断对象的引用数量来决定对象是否可以被回收。
2.可达性分析算法:
是通过判断对象的引用链是否可达来决定对象是否可以被回收。
三、垃圾收集算法
1.标记清除算法:
标记-清除算法分析和清除两个阶段。该算法首先从根集合进行扫描,对存活的对象标记,标记完毕后,再扫描整个空间中未被标记的对象并进行回收。
2.复制算法
复制算法将可用内存按容量划分为大小相等的两块,每次只使用其中的一块,当这一块的内存用完了,就将还存活的对象复制到另外一块上面,然后再把已使用过的空间一次清理掉。
3.标记整理算法
标记整理算法的标记过程类似标记清除算法,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都想一端移动,然后直接清理掉端边界以外的内存,类似于磁盘整理过程,该垃圾回收算法使用与对象存活率高的场景。
4.分代收集算法
不同的对象的生命周期是不一样的,而不同生命周期的对象位于堆中不同的区域,因此对堆内存不同的区域采用不同的策略进行回收可以提高JVM的执行效率。
a.新生代:新生代的目标是尽可能快速的收集掉那些生命周期短的对象,一般情况,所有新生成的对象首先是放在新生代的。在垃圾回收时,先将eden区存活对象复制到survivor0区,然后清空eden区,当这个survivor0也满了时,则将eden区和survivor0区存活对象复制到survivor1中,然后清空eden和这个survivor0,此时survivor0区是空的,然后交换survivor0和survivor1区的角色,即保存survivor0区空,如此往复,
b.老年代:老年代存放的都是一些生命周期较长的对象,就像上面叙述的那样,在新生代中经历了N次垃圾回收后任然存活的对象就会别放到老年代中。
c.永久代:永久代主要用于存放静态文件,如Java类,方法等
5.总结
四、垃圾收集器
如果说垃圾收集算法是内存回收算法的方法论,那么垃圾收集器就是内存回收的具体实现,有7种作用不同的分代的收集器,其中用于回收新生代的收集器包括Serial、PraNew、Parallel Seavenge,回收老年代的收集器包括Serial Old、Parallel Old、CMS,还有用于回收整个Java堆的GI收集器,不同收集器之间的连线表示它们可以搭配使用的。(还有一些细节,等下次用空补上)
五、内存分配与回收策略
1.对象优先在Eden分配,但Eden区没有足够空间进行分配时,虚拟机将发起一次MinorGC
2.大对象直接进入老年代
3.长期存活的对象讲进入老年代
4.动态对象年龄的判定
六、Java的内存泄漏问题:
内存泄漏是指该内存空间使用完毕之后未回收,在不涉及复杂数据结构的一般情况写,Java的内存泄漏表现为一个内存对象的生命周期超出了程序需要它的长度。
1.HashMap、Vector等集合的静态使用最容易出现内存泄漏问题,
2.各种资源连接包括数据库连接、网络连接、IO连接等没有显示调用close关闭,不被GC回收导致内存泄漏
3.监听器的使用,在释放对象的同时没有相应删除监听器的时候也可能导致内存泄漏。
七、知识点的补充
1.方法区的回收
方法区的内存回收目标主要针对常量池的回收和对类型的卸载。