方法一:标记清除算法
分两个阶段,标记和清除。
标记阶段需要标记出所有需要回收的对象。
清除阶段回收被标记的对象所占用的空间。
问题:内存碎片化严重
方法二:复制算法
把内存等分成两块,每次只使用一块,当这块内存快满的时候,扫描这块存活的对象,复制到另一块上,原来那块内存清掉
优点:实现简单,不易产生内存碎片
缺点:1、真正使用内存是实际内存的一半。2、如果存活对象多,算法效率很差
方法三:标记整理算法
这个方法是上面两个方法的结合版本。
分两个阶段,标记和整理
标记阶段需要标记出所有需要回收的对象。
整理阶段,将存活的对象移动到内存另一端,然后再清除这端的数据。
方法四:分代收集算法
分代分三代,分别是新生代、老年代、永久代(元数据)
新生代和复制算法
新生代分三个区,分别是EdenSpace、FromSpace、ToSpace
解释新生代是怎么用复制算法完成gc:
步骤一:Eden和From存活对象复制到To,并且年龄+1(年龄>15或To内存不够了就放老年区)
步骤二:清空原来的Eden和From
步骤三:To和From互换(这次gc的To变下次gc的From,From同理)
老年代和标记清除算法
原因:因为老年代的对象存活率高,标记后清理掉无用对象就好
永久代(元数据)
永久代(java8之前):gc永远不会清理,会抛出oom异常
元数据:不放在虚拟机,放在本地内存中。优点是加载多少元数据由系统实际空间决定。
一些学习的小方法总结:遇到概念性的东西,读起来确实是又臭又长,但是如果静下心来去找这些概念的规律,我觉得可以简单粗暴的把概念分成是什么,为什么(哪里好,哪里不好),怎么做。