JAVA运行时内存区域
一、垃圾收集算法
GC管理的主区域是Java堆,一般情况下只针对堆进行垃圾回收。方法区、栈、本地方法区 不被GC所管理,因而选择这些区域内的对象作为GC roots,被GC roots引用的对象不被GC回收。
GC(Garbage Collector) roots,特指的是垃圾收集器(Garbage Collector)的对象,GC会收集那些不是GC roots且没有被GC roots引用的对象【存活对象】
一般的可标记为存活对象的是
1.虚拟机栈中引用的对象
2.本地方法栈中native方法引用的对象
3.方法区中静态属性引用的变量
4.方法区中常量引用的对象
二、算法分析
1. 标记-清楚算法(Mark-Sweep)
应用场景: 针对老年代的CMS收集器;
思路:
标记: 遍历获取所有的GC Roots,然后将所有GC Roots 可达的对象标记为存活对象。
清楚:遍历堆中所有的对象,将没有标记的对象全部清除掉。
优点:
基于最基础的可达性分析算法,它是最基础的收集算法
后续的收集算法都是基于这种思路并对其不足进行改进得到的
缺点:
效率问题,标记和清除过程的效率都不高。
空间问题,标记清除之后会产生大量不连续的内存碎片。【空间碎片太多可能会导致,碎片过多会导致大对象无法分配到足 够的连续内存,从而不得不提前触发GC,甚至Stop The World】
2.复制算法(Copying)一般用于新生代
应用场景: 如Serial收集器、ParNew收集器、Parallel Scavenge收集器、、G1(从局部看);
产生:优化标记/清除算法的效率低、内存碎片多的问题
思路:
(A)内存按容量划分为大小相等的两块,每次使用其中的一块。
(B)当一块内存用完了,就将还存活的对象复制到另一块上(而后使用这一块)。
(C)再把已使用过的那块内存空间一次清理掉,而后重复步骤B。
优点:
这使得每次都是只对整个半区进行内存回收。
内存分配时也不用考虑内存碎片等问题(可使用"指针碰撞"的方式分配内存)。
实现简单,运行高效。
缺点:
空间浪费[将内存缩小为原来的一半,浪费了一半的内存空间,代价太高【解决:可以改良,不按1:1比例划分】
效率随对象存活率升高而变低【当对象存活率较高时,需要进行较多复制操作,效率将会变低(解决:后面的标记-整理算法)】
3、标记-整理算法(Mark-Compact)一般用于老年代
应用场景:部分一般收集器采用这种算法来回收老年代,如Serial Old收集器、G1(从整体看);
产生: 复制算法在对象存活率较高时就要执行较多的复制操作,效率将会变低。以及50%的空间浪费
思路:
标记:标记过程与"标记-清除"算法一样;
整理: 让所有存活的对象都向一端移动,按照内存地址次序依次排列,然后直接清理掉端边界[GCRoot引用到的最后一个存活 对象]以外的内存。【 所有现代的标记-整理回收器均使用滑动整理】
优点:
不会像复制算法,效率随对象存活率升高而变低。
不会像标记-清除算法,产生内存碎片。
可以解决循环引用的问题 。
必要时才回收(内存不足时)
缺点:
回收时,应用需要挂起,也就是stop the world【 停止应用程序,这会导致用户体验非常差】
清理出来的空闲内存不是连续的。
除像标记-清除算法的标记过程外,还多了需要整理的过程,效率更低。
4、分代收集算法[像是调度员]
应用场景:目前几乎所有商业虚拟机的垃圾收集器都采用分代收集算法。[Serial、Serial Old、ParNew、Parallel Scavenge、Parallel Old、CMS]
产生:结合不同的收集算法处理不同区域。
思路:
根据对象存活周期的不同将内存划分为几块.
根据各个年代的特点采用最适当的收集算法;
优点:
可以根据各个年代的特点采用最适当的收集算法;
缺点:
还是不能控制每次垃圾收集的时间。
补充:
在新生代中,存活对象少,存活率低。于是选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。
在老年代中,存活对象多,存活率高。于是选用标记-清理 ”或“ 标记-整理”
三、对比
效率: 复制算法 > 标记/整理算法 > 标记/清除算法(标记/清除算法有内存碎片问题,给大对象分配内存时可能会再次出发垃圾回收)
内存整齐率:复制算法 = 标记/整理算法 > 标记/清除算法
内存利用率:标记/整理算法 = 标记/清除算法 > 复制算法
结果:标记/清除算法已经是比较落后了,不过作为最基础的收集算法!还是有地方可以采用
目前最好的算是分代收集算法了!毕竟几乎所有商业虚拟机的垃圾收集器都采用了。 结合前三个算法的优点, 将算法组合使用进行垃圾回收!
分代收集算法的原理是 采用复制算法来收集新生代,采用标记/清理算法或者标记/整理算法收集老年代。
共同点
当GC线程启动时(即进行垃圾收集),应用程序都要暂停(Stop The World)
参考文档
https://blog.csdn.net/clover_lily/article/details/80160726