设为首页 加入收藏

TOP

深入理解Java垃圾回收机制(二)
2015-07-16 12:55:21 来源: 作者: 【 】 浏览:6
Tags:深入 理解 Java 垃圾 回收 机制
收集器(复制算法)


  新生代单线程收集器,标记和清理都是单线程,优点是简单高效。


Serial Old收集器(标记-整理算法)


  老年代单线程收集器,Serial收集器的老年代版本。


ParNew收集器(停止-复制算法) 


  新生代收集器,可以认为是Serial收集器的多线程版本,在多核CPU环境下有着比Serial更好的表现。


Parallel Scavenge收集器(停止-复制算法)


  并行收集器,追求高吞吐量,高效利用CPU。吞吐量一般为99%, 吞吐量= 用户线程时间/(用户线程时间+GC线程时间)。适合后台应用等对交互相应要求不高的场景。


Parallel Old收集器(停止-复制算法)


  Parallel Scavenge收集器的老年代版本,并行收集器,吞吐量优先


CMS(Concurrent Mark Sweep)收集器(标记-清理算法)


  高并发、低停顿,追求最短GC回收停顿时间,cpu占用比较高,响应时间快,停顿时间短,多核cpu 追求高响应时间的选择


四、GC的执行机制


  由于对象进行了分代处理,因此垃圾回收区域、时间也不一样。GC有两种类型:Scavenge GC和Full GC。


Scavenge GC


一般情况下,当新对象生成,并且在Eden申请空间失败时,就会触发Scavenge GC,对Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。这种方式的GC是对年轻代的Eden区进行,不会影响到年老代。因为大部分对象都是从Eden区开始的,同时Eden区不会分配的很大,所以Eden区的GC会频繁进行。因而,一般在这里需要使用速度快、效率高的算法,使Eden去能尽快空闲出来。


Full GC


对整个堆进行整理,包括Young、Tenured和Perm。Full GC因为需要对整个对进行回收,所以比Scavenge GC要慢,因此应该尽可能减少Full GC的次数。在对JVM调优的过程中,很大一部分工作就是对于FullGC的调节。有如下原因可能导致Full GC:


  1.年老代(Tenured)被写满


  2.持久代(Perm)被写满


  3.System.gc()被显示调用


  4.上一次GC之后Heap的各域分配策略动态变化


五、Java有了GC同样会出现内存泄露问题


1.静态集合类像HashMap、Vector等的使用最容易出现内存泄露,这些静态变量的生命周期和应用程序一致,所有的对象Object也不能被释放,因为他们也将一直被Vector等应用着。


Static Vector v = new Vector();
for (int i = 1; i<100; i++)
{
? ? Object o = new Object();
? ? v.add(o);
? ? o = null;
}


在这个例子中,代码栈中存在Vector 对象的引用 v 和 Object 对象的引用 o 。在 For 循环中,我们不断的生成新的对象,然后将其添加到 Vector 对象中,之后将 o 引用置空。问题是当 o 引用被置空后,如果发生 GC,我们创建的 Object 对象是否能够被 GC 回收呢?答案是否定的。因为, GC 在跟踪代码栈中的引用时,会发现 v 引用,而继续往下跟踪,就会发现 v 引用指向的内存空间中又存在指向 Object 对象的引用。也就是说尽管o 引用已经被置空,但是 Object 对象仍然存在其他的引用,是可以被访问到的,所以 GC 无法将其释放掉。如果在此循环之后, Object 对象对程序已经没有任何作用,那么我们就认为此 Java 程序发生了内存泄漏。


2.各种连接,数据库连接,网络连接,IO连接等没有显示调用close关闭,不被GC回收导致内存泄露。


3.监听器的使用,在释放对象的同时没有相应删除监听器的时候也可能导致内存泄露。


首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇深入理解Java:内部类 下一篇Linux Shell在while中用read从键..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: