java中的gc垃圾回收机制

来源:转载

1、所谓垃圾回收机制:是JVM对堆内存区域的回收

2、怎样确定一个线程是否可以被回收:

方法一:计数法:在内存中用计数器记录该对象被引用的次数,当被引用时就+1,对象释放就-1,当计数器中数为0时说明是该回收的线程了。但是这种方法有漏洞:当A 和B两个对象相互引用形成循环,那么计数器中的数就一直是1,这样就不会被察觉得到。这样就用到了

第二种方法:

 


方法二:根搜索:就是找这个对象有没有路径可以到达根,如果有则不回收,如果没有那么进行回收。

如下图:对象D访问不到根对象,所以就会被回收

以下对象会被认为是root对象:

  • 被启动类(bootstrap加载器)加载的类和创建的对象
  • jvm运行时方法区类静态变量(static)引用的对象
  • jvm运行时方法去常量池引用的对象
  • jvm当前运行线程中的虚拟机栈变量表引用的对象
  • 本地方法栈中(jni)引用的对象
3、在根搜索所得到的回收对象前有一个复活环节:有且仅有一次复活机会,如果不能复活,那么就会永远死去,呵呵。实现他的函数是finalize(),我们要重写一下:

package deadToLive;/** * Created by Administrator on 2015/11/3 0003. */public class DeadToAlive { private static DeadToAlive deadToAlive; public void finalize() throws Throwable{ try { super.finalize(); DeadToAlive.deadToAlive=this; } catch (Throwable throwable) { throwable.printStackTrace(); } } public static void main(String[] args) throws InterruptedException { DeadToAlive.deadToAlive=new DeadToAlive(); DeadToAlive.deadToAlive=null; System.gc(); Thread.sleep(500); if(deadToAlive!=null) System.out.println("Alive"); else System.out.println("Dead"); DeadToAlive.deadToAlive=null; System.gc(); Thread.sleep(500); if(deadToAlive!=null) System.out.println("Alive"); else System.out.println("Dead"); }}
首先标记一次,将其放在F-queue队列中,等待执行finalize()函数,执行后GC进行二次标记,而此时赴会的不会被标记,只有在执行完finalize()后仍然dead的那么就直接进行回收了。

4、垃圾回收的策略:

(1)标记--清除:直接将内存中二次标记的的线程进行消除,这样简便但是会造成碎片的产生,内存的浪费。

(2)标记--复制:将堆分成8:1:1的1个Eden和2个survivor构成新生代。

每次将Eden和Survivor中存活的对象复制到另一块空闲的Survivor中。这三块区域并不是堆的全部,而是构成了新生代
从下图可以看到这三块区域如何配合完成GC的,具体的对象空间分配以及晋升请


为什么不是全部呢?如果回收时,空闲的那一小块Survivor不够用了怎么办?这就是老年代的用处。当不够用时,这些对象将直接通过分配担保机制进入老年代。那么老年代也使用标记-复制策略吧?当然不行!(老年代是使用标记--整理策略)老年代中的对象可不像新生代中的,每次回收都会清除掉大部分。如果贸然采用复制的策略,老年代的回收效率可想而知。(3)标记--整理:将所有Alive下来的线程都整理到一块去,这样解决了(1)的局限性,并且满足老年代的特点。

5、虚拟机上的收集器:

(1)新生代的GC:

serial:单线程,当他进行回收时,其它工作线程必须暂停

parNew:多线程

parallel scavenge:吞吐量优先

(2)老年代的GC:
serial old:单线程

parallel old:多线程

CMS:是基于标记--清除

6、什么情况下进行GC:

(1)新生代回收:

Minor GC(新生代回收)的触发条件比较简单,Eden空间不足就开始进行Minor GC回收新生代。(2)老年代回收:

(1)老年代空间不足(2)PermSpace空间不足(3)统计得到的Minor GC晋升到老年代的平均大小大于老年代的剩余空间这里注意一点:PermSpace并不等同于方法区,只不过是Hotspot JVM用PermSpace来实现方法区而已,有些虚拟机没有PermSpace而用其他机制来实现方法区。7、要回收对象空间分配和晋升:对象优先分到新生代的Eden中大对象分配到老年代中新生代中的对象每熬过一次Minor GC就会+1岁,当为15岁时就会进入老年代


资源来源:http://blog.csdn.net/dc_726/article/details/7934101


分享给朋友:
您可能感兴趣的文章:
随机阅读: