首先我我们需要知道gc算法 和垃圾回收算法
第一种
引用计数算法,其原理是:此对象有一个引用,则+1;删除一个引用,则-1。只用收集计数为0的对象 但是这个并不能解决循环引用的问题 所以这个算法基本上已经淘汰了
第二种
收索树算法
其原理是 设立若干种根对象,当任何一个根对象到某一个对象均不可达时,则认为这个对象是可以被回收的。
可以做根对象的有
**1、虚拟机栈中的引用的对象。
2、方法区中的类静态属性引用的对象。
3、方法区中的常量引用的对象。
4、本地方法栈中JNI的引用的对象。**
上面的两个算法只是解决了谁可以被回收但是没有解决什么时候回收 怎么回收这个问题
第一种
标记清除算法
用通俗的话解释一下标记/清除算法,就是当程序运行期间,若可以使用的内存被耗尽的时候,GC线程就会被触发并将程序暂停,随后将依旧存活的对象标记一遍,最终再将堆中所有没被标记的对象全部清除掉,接下来便让程序恢复运行
缺点
程序会有暂停时间降低了用户的体验度
这种方式清理出来的空闲内存是不连续的,
复制算法
首先需要两个差不多大的空间 若可以使用的内存被耗尽的时候 回收算法开始工作,把一个区域里面还活着的对象地址复制到另一个空间里面按照顺序排好
缺点:
它浪费了一半的内存
如果对象的存活率很高,我们可以极端一点,假设是100%存活,那么我们需要将所有对象都复制一遍,并将所有引用地址重置一遍。
标记/整理算法
先通过将存活的对象标记 然后移动所有存活的对象,且按照内存地址次序依次排列,然后将末端内存地址以后的内存全部回收
缺点:
效率也不高,不仅要标记所有存活对象,还要整理所有存活对象的引用地址
相信经过前面的简绍 你对java的垃圾回收有了一个初步的认识
下面来看一下几种算法的比较(极端情况下)
效率:复制算法>标记/整理算法>标记/清除算法
内存整齐度:复制算法=标记/整理算法>标记/清除算法。
内存利用率:标记/整理算法=标记/清除算法>复制算法。
对于垃圾收集器差不多都是从上面重上面演变的
Serial收集器
-XX:+UseSerialGC
新生代、老年代使用串行回收
新生代复制算法
老年代标记-压缩
并行收集器
ParNew
-XX:+UseParNewGC(new代表新生代,所以适用于新生代)
新生代并行
老年代串行
Serial收集器新生代的并行版本
在新生代回收时使用复制算法
多线程,需要多核支持
-XX:ParallelGCThreads 限制线程数量
Parallel收集器
类似ParNew
新生代复制算法
老年代标记-压缩
更加关注吞吐量
-XX:+UseParallelGC
使用Parallel收集器+ 老年代串行
-XX:+UseParallelOldGC
使用Parallel收集器+ 老年代并行
CMS收集器
Concurrent Mark Sweep 并发标记清除(应用程序线程和GC线程交替执行)
使用标记-清除算法
并发阶段会降低吞吐量(停顿时间减少,吞吐量降低)
老年代收集器(新生代使用ParNew)
-XX:+UseConcMarkSweepGC
网友评论