程序计数器、Java虚拟机栈、本地方法栈分配的内存是肯定的,生命周期与线程一样。因此不需要过多考虑回收问题。算法
而Java堆和方法区仅仅有运行时才知道有哪些对象被建立,需要多少内存,这部分的内存分配和回收是动态的。数组
给对象加入引用计数器,有地方引用时+1,引用失效时-1。不论什么时刻计数器为0的对象就是不可能在被使用的。但是!markdown
不能解决对象间互相引用的问题,因此主流虚拟机不用这种方法。post
经过一系列称为“GCRoots”的对象做为起始点,開始向下搜索,走过的路径称为引用链,当一个对象到GCRoots没有不论什么引用链相连时,则该对象不可用。
可做为GCRoots的对象包含:线程
至少要经历两次标记过程:指针
不论什么对象的finalize()方法仅仅能被调用一次,因此第一次逃脱后第二次将没法逃脱。对象
主要回收废弃常量和没用的类。生命周期
不足:队列
将内存分为相等大小的两块。每次仅仅使用当中一块。当一块用完时将活着的对象拷贝到还有一块上面。而后一次清除使用过的那块内存。图片
长处:仅仅要移动堆顶指针。按顺序分配内存就能够。实现简单。运行高效。
缺点:内存缩小为原来的一半。在对象存活率高的时候不适用,适合新生代。
IBM策略:採用一个较大的Eden空间(80%)和两个较小的Survivor空间(10%),每次使用Eden和一个Survivor。
适用于老年代,标记后让所有存活的对象都向一端移动。而后直接清理掉端边界之外的内存。
将Java堆分为新生代和老年代。依据各个年代的特色採用最适合的收集算法。