JVM垃圾回收?看这一篇就够了!
深入理解JVM垃圾回收机制1、垃圾回收需要解决的问题及解决的办法总览
下面就是如何判定对象为垃圾对象 2、引用计数法在对象中添加一个引用计数器,当有地方引用这个对象的时候,引用技术器得值就+1,当引用失效的时候,计数器得值就-1 下面我们运行实例代码来看,JVM在循环引用时,是否能被收集(如果回收了就说明垃圾回收器用的不是引用计数法)。 如果想打印日志信息,请填入如下参数。 -verbose:gc -XX:+PrintGCDetails 其中我们需要将每个对象的所占内存扩大,因此我们声明一个大点的空间。 测试实验代码如下: public class A { private Object instance; public A() { byte[] m = new byte[20*1024*1024]; } public static void main(String[] args) { A a1 = new A(); A a2 = new A(); a1.instance=a2; a2.instance=a1; a1=null; a2=null; System.gc(); //parallel 默认采用的垃圾回收器 } } 运行结果如下所示:
这里我们会看到 22446K->648J这里,我们的对象被回收了,这就说明我们JVM采用的垃圾回收算法并不是引用计数法。 3、可达性分析法算法如名,可达性分析法就是从GCroot结点开始,看能否找到对象。 GCroot结点开始向下搜索,路径称为引用链,当对象没有任何一条引用链链接的时候,就认为这个对象是垃圾,并进行回收。 那么什么是GCroot呢(虚拟机在哪查找GCroot)。
目前主流JVM采用的垃圾判定算法就是可达性分析法。 至此垃圾判定算法结束 垃圾回收算法开始 4、标记-清除算法存在的问题:
5、复制算法下面是java内存常规划分
下面是堆内存的划分
下面就是过程: 被标记的黑色就是需要回收的 将白色区域复制下面,然后清空上面的 这样就完成了内存的连续分配,但是引来一个问题。 为了解决这个问题,我们对内存就进行了划分。
复制算法,我们需要将上面的思路,将Eden中需要回收的对象放到Survivor,然后清除。 这里我们即提高了效率,又减少了内存分配。 如果Survivor不够放,那就扔到老年代里,或者其他方法,反正有内存担保。 6、标记-整理算法复制算法主要针对新生代内存收集方法。 主要步骤:标记-整理-清除 如下图所示 然后将右面的进行删除计科达到回收效果。 7、分代收集算法分代收集算法是根据内存的分代选择不同的算法。 显而易见,这是上面俩种算法的优点糅合在一起的应用。 至此我们总结了所有垃圾回收算法。 8、Serial收集器特点:
运行机制如下所示 缺点:慢 用处:在客户端上运行还是比较有效。没有线程的开销,所以在客户端还是比较好用的。 9、ParNew收集器特点:
实现原理都是复制算法。 缺点:
10、Parallel Scavenge 收集器主用算法:复制算法(新生代收集器) 吞吐量 = (执行用户代码消耗的时间)/(执行用户代码的时间)+ 垃圾回收时所占用的时间 优点:吞吐量优化(CPU用于运行用户代码的时间与CPU消耗的总时间的比值) 关于控制吞吐量的参数如下 -XX:MaxGCPauseMills #垃圾收集器的停顿时间 -XX:GCTimeRatio #吞吐量大小 当停顿时间过小时,内存对应变小,回收的频率增大。因此第一个参数需要设置的合理才比较好。 总的来说:客户端可用,服务端最好不用。 11、CMS收集器(Concurrent Mark Sweep)采用算法:标记清除算法。
CMS是一个并发的收集器。 目标是:减少延迟,增加响应速度
12、G1收集器(面向服务端)最牛的垃圾收集器。
13、小结:至此我们就已经掌握了大部分GC的知识。这可不是一个小工程,希望要好好吸收知识。。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |