java进程在启动之后会创建垃圾回收线程,堆内存中的无用对象来进行回收.
触发垃圾回收的时候:当内存不足的时候回触发垃圾回收进程对内存中的垃圾进行回收.
在java中的java.utilObject类中提供了一个finalize()方法.当jvm不在确定有引用直线某个对象的时候垃圾回收器,在这个对象上调用这个方法.调用这个方法之后标志着这个对象即将死亡.之后垃圾回收进程对这个对象进行回收.
垃圾回收如何判断对象已死亡
使用可达性算法来判断这个对象师傅可以回收.创建了GC roots 这个引用对象,可以搜索的路线表示GC roots引用链.当一个对象不可以到达GC roots这个引用对象的时候表示无用对象.
GC管理的区域
永久代:方法区:在这个区域主要回收无用的类和废弃的常量.回收效率比较低.
java堆:GC对它管理的区域划分为新生代和老年代.主要回收的是对象.
1.新生代:新生代主要划分为Eden区和s区和s0区.
新生代的垃圾回收的速率好远远大于老年代,主要是创建的对象都在Eden区.
老年代哪里回收速率要低于新生代10倍以上.
垃圾回收的算法:
1.标记--清除算法:这是一个老年代算法.首先将需要回收的对象进行标记,之后再进行标记之后的对象进行回收.这个算法的效率比较低,因为进行了两部,而且空间不再是连续的了,当创建一个大对象的时候没有足够的空间,而又会出发GC.
2.复制算法:这个算法主要是新生代算法.他首先将内存划分出来一片空白的区域,之后将不需要清除的对象复制过去,之后再将上面的空间全部清除,这个算法主要是空间使用率不是很高.
3.标记--真理算法:这是一个老年代算法,其实他也是标记--清除的方法.但是后序步骤是将存活的对象向一端移动.,然后直接清除边界意外的对象.
4.分代算法:当前的JVM垃圾收集器都是采用的分代算法的思想.这个主要针对的是新生区,因为新生代的对象98%都是朝生夕死的,,所以并不是按照复制算法的50%的划分内存.而是将Eden区:s区=8:1的比例来划分内存的.
垃圾回收的过程
当Eden区的内存不足的视乎,会触发GC,对象优先放在Eden区域的.而Edden区和s区存活的对象复制到s0区域之后对Eden区和s区回收.垃圾回收结束之后新创建的对象放在Eden区,当Eden区的内存不足的时候重复上面的步骤.
年轻代的对象晋升为老年代对象.
s区内存不足的时候有分配担保机制进入老年代.
老年代内存不足的时候也会触发GC.
内存分配的和回收的策略.
大对象优先放在Eden区,但是当Eden区域的内存不够放下大对象的时候就进入老年代存放.
长期存活的对象,进入老年代.JVM里面的默认阈值是15,当年轻代的GC回收了15次以上,这个对象依然在存活的时候就进入了老年代.
垃圾回收对用户线程的影响
垃圾回收的时候,用户线程可能需要停止,这会影响用户线程的执行效率的.
吞吐量优先:总的停顿时间比较小.
用户体验优先:单词停顿时间比较小,但是总的停顿时间比较长.
垃圾收集器:
新生代: Serial收集器.这个是单线程,使用的复制算法用户线程需要暂停 的.
ParNew收集器:这个是多线程的,使用的复制算法,用户线程需要暂停的.搭配着CMS收集器一起使用,这个收集器主要是用户体验优先.
Parallel Scavenge收集器 ,这个多线程,使用的算法是复制算法,,吞吐链优先的.
老年代收集器:Serial Old收集器,这个是单线程的,使用的标记--整理算法.用户线程需要暂停的.
Parallel Old收集器,这个是多线程的,使用的标记--整理算法.吞吐量优先的,
CMS收集器:多线程的,使用的标记-清除算法.
并发收集,低停顿.
整个为四个过程:初始标记,并发标记,重新标记,(这个过程需要用户线程暂停)并发清除.
缺陷:在cup调度的时候加入了垃圾回收线程之后会影响,用户线程的执行效率, 在收集的时候会产生浮动的垃圾,可能会再次出发Full GC. 收集完之后空间不是连续的.
用户体验优先的时候 ParNew和CMS搭配使用
吞吐量优先的时候 Paralle Scavenge 和Parallel Old搭配使用.
G1垃圾回收器:
这是一个全区域垃圾回收机制,是用户体验优先.而他局部采用的是复制算法,而整体采用的是标记--整理算法.
原文:https://www.cnblogs.com/yuzhenghan/p/13188070.html