垃圾回收主要内容:
1. 那些内存需要回收?
2. 什么时候回收?
3. 如何回收?
垃圾回收主要针对运行时数据区那些区域?
运行时数据区的线程私有区域有:虚拟机栈,本地方法栈,程序计数器等;
栈中的栈帧随着方法的进入和退出执行入栈和出栈,每个栈帧的内存分配在编译期就已经确定;
随着线程或方法的结束,内存也随着回收;
运行时数据区的线程共享区域有:方法区,堆;
方法区和堆只有程序处于运行期才能确定创建那些对象,因此这部分内存分配和回收都是动态的;
垃圾回收的重点区域;
一,对象存活判断
1,引用计数算法
给对象添加一个引用计数器,被引用时计数器值+1,引用失效计数器值-1,当计数器值为0时对象不可能再被使用;
主流Java虚拟机未选用该算法管理内存(未解决对象之间相互循环引用的问题)
实现简单,判断效率高(应用:FlashPlayer,Python等)
2,可达性分析算法
将"GC Roots"对象作为起始节点,向下搜索,搜索走过的路径为引用链;当一个对象到GC Roots没有引用链时,则该对象是不可用的;
可作为"GC Roots"的对象:
【1】,方法区中静态属性引用的对象
【2】,方法区中常量引用的对象
【3】,虚拟机栈引用的对象 (栈帧中本地变量表)
【4】,本地方法栈中JNI引用的对象 (Native方法)
二,垃圾回收算法
1,标记-清除算法
定义:先标记要回收的对象,然后统一回收;
适用:存活对象较多的垃圾回收
缺点:
【1】,效率低; 标记和清除的过程效率不高;
【2】,空间问题; 标记清除后产生大量不连续的内存碎片,给大对象分配内存时没有足够连续的内存空间,导致提前出发垃圾回收动作。
2,复制算法
定义:将可用内存划分成相等大小两块,每次只使用其中一块,当这一块用完后将还存活的对象复制到另一块,
然后将已使用过的内存一次清理。
适用:存活对象较少的垃圾回收
优点:每次对整个半区进行内存回收,不用考虑内存碎片问题,只要移动堆顶指针,按顺序分配内存即可;
实现简单,运行高效
缺点:将内存缩小了一半
其他:
将新生代内存按照8:1:1分为Eden,From Survivor,To Survivor三个空间,每次使用Eden和From Survivor两个空间给对象分配内存,
当内存不足垃圾回收时,将存活对象复制到To Survivor空间,然后清理Eden和From Survivor空间;这样相当于内存指浪费了10%;
如果10%的To Survivor空间不够存放存活对象时需要老年代进行分配担保(将存活对象通过分配担保机制直接进入老年代)
3,标记-整理算法
定义:先标记要回收的对象,将存活对象移至一端,最后清理端边界以外的内存
4,分代收集算法
定义:根据对象存活周期将内存划分为新生代和老年代,然后根据每个年代的特点使用合适的回收算法;
如:新生代存活对象少可以采用复制算法; 老年代存活对象多并且没有分配担保必须使用标记清理或标记整理回收算法
三,垃圾回收器
1,