首页 > 试题广场 >

以下哪些jvm的垃圾回收方式采用的是复制算法回收

[不定项选择题]
以下哪些jvm的垃圾回收方式采用的是复制算法回收
  • 新生代串行收集器
  • 老年代串行收集器
  • 并行收集器
  • 新生代并行回收收集器
  • 老年代并行回收收集器
  • cms收集器
两个最基本的java回收算法:复制算法和标记清理算法
复制算法:两个区域A和B,初始对象在A,继续存活的对象被转移到B。此为新生代最常用的算法
标记清理:一块区域,标记可达对象(可达性分析),然后回收不可达对象,会出现碎片,那么引出
标记-整理算法:多了碎片整理,整理出更大的内存放更大的对象
两个概念:新生代和年老代
新生代:初始对象,生命周期短的
永久代:长时间存在的对象
整个java的垃圾回收是新生代和年老代的协作,这种叫做分代回收。
P.S:Serial New收集器是针对新生代的收集器,采用的是复制算法
Parallel New(并行)收集器,新生代采用复制算法,老年代采用标记整理
Parallel Scavenge(并行)收集器,针对新生代,采用复制收集算法
Serial Old(串行)收集器,新生代采用复制,老年代采用标记整理
Parallel Old(并行)收集器,针对老年代,标记整理
CMS收集器,基于标记清理
G1收集器:整体上是基于标记 整理 ,局部采用复制

综上:新生代基本采用复制算法,老年代采用标记整理算法。cms采用标记清理。
编辑于 2017-12-29 09:13:26 回复(35)
我成功了避过了所有正确答案
发表于 2016-03-24 16:29:34 回复(103)
🐴
发表于 2022-02-24 08:48:14 回复(0)
看来我有必要好好看看一些深入一点的书籍。。。
发表于 2017-01-17 11:51:29 回复(1)
http://blog.csdn.net/dc_726/article/details/7934101# 垃圾回收总结 看看吧
发表于 2016-08-14 12:08:37 回复(0)

垃圾回收包含的内容不少,但顺着下面的顺序捋清知识也并不难。首先要

搞清垃圾回收的范围(栈需要GC去回收吗?),然后就是回收的前提条件

如何判断一个对象已经可以被回收(这里只重点学习根搜索算法就行了),

之后便是建立在根搜索基础上的三种回收策略,最后便是JVM中对这三种

策略的具体实现。


1.范围:要回收哪些区域?


Java方法栈、本地方法栈以及PC计数器随方法或线程的结束而自然被回收,

所以这些区域不需要考虑回收问题。Java堆和方法区是GC回收的重点区域,

因为一个接口的多个实现类需要的内存不一样,一个方法的多个分支需要

的内存可能也不一样,而这两个区域又对立于栈可能随时都会有对象不再

被引用,因此这部分内存的分配和回收都是动态的。



2.前提:如何判断对象已死?


(1)引用计数法


引用计数法就是通过一个计数器记录该对象被引用的次数,方法简单高效,

但是解决不了循环引用的问题。比如对象A包含指向对象B的引用,对象B

也包含指向对象A的引用,但没有引用指向A和B,这时当前回收如果采用的

是引用计数法,那么对象A和B的被引用次数都为1,都不会被回收。


下面是循环引用的例子,在Hotspot JVM下可以被正常回收,可以证实JVM

采用的不是简单的引用计数法。通过-XX:+PrintGCDetails输出GC日志。

[java] view plaincopy

  1. package com.cdai.jvm.gc;  

  2.   

  3. public class ReferenceCount {  

  4.   

  5.     final static int MB = 1024 * 1024;  

  6.       

  7.     byte[] size = new byte[2 * MB];  

  8.       

  9.     Object ref;  

  10.       

  11.     public static void main(String[] args) {  

  12.         ReferenceCount objA = new ReferenceCount();  

  13.         ReferenceCount objB = new ReferenceCount();  

  14.         objA.ref = objB;  

  15.         objB.ref = objA;  

  16.           

  17.         objA = null;  

  18.         objB = null;  

  19.           

  20.         System.gc();  

  21.         System.gc();  

  22.     }  

  23.   

  24. }  


[Full GC (System) [Tenured: 2048K->366K(10944K), 0.0046272 secs] 4604K->366K(15872K), [Perm : 154K->154K(12288K)], 0.0046751 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 


(2)根搜索


通过选取一些根对象作为起始点,开始向下搜索,如果一个对象到根对象

不可达时,则说明此对象已经没有被引用,是可以被回收的。可以作为根的

对象有:栈中变量引用的对象,类静态属性引用的对象,常量引用的对象等。

因为每个线程都有一个栈,所以我们需要选取多个根对象。


附:对象复活


在根搜索中得到的不可达对象并不是立即就被标记成可回收的,而是先进行一次

标记放入F-Queue等待执行对象的finalize()方法,执行后GC将进行二次标记,复活

的对象之后将不会被回收。因此,使对象复活的唯一办法就是重写finalize()方法,

并使对象重新被引用。

[java] view plaincopy

  1. package com.cdai.jvm.gc;  

  2.   

  3. public class DeadToRebirth {  

  4.   

  5.     private static DeadToRebirth hook;   

  6.       

  7.     @Override  

  8.     public void finalize() throws Throwable {  

  9.         super.finalize();  

  10.         DeadToRebirth.hook = this;  

  11.     }  

  12.       

  13.     public static void main(String[] args) throws Exception {  

  14.         DeadToRebirth.hook = new DeadToRebirth();  

  15.         DeadToRebirth.hook = null;  

  16.         System.gc();  

  17.         Thread.sleep(500);  

  18.         if (DeadToRebirth.hook != null)  

  19.             System.out.println("Rebirth!");  

  20.         else  

  21.             System.out.println("Dead!");  

  22.           

  23.         DeadToRebirth.hook = null;  

  24.         System.gc();  

  25.         Thread.sleep(500);  

  26.         if (DeadToRebirth.hook != null)  

  27.             System.out.println("Rebirth!");  

  28.         else  

  29.             System.out.println("Dead!");  

  30.     }  

  31.       

  32. }  


要注意的两点是:

第一,finalize()方法只会被执行一次,所以对象只有一次复活的机会。

第二,执行GC后,要停顿半秒等待优先级很低的finalize()执行完毕。



3.策略:垃圾回收的算法


(1)标记-清除


没错,这里的标记指的就是之前我们介绍过的两次标记过程。标记完成后就可以

对标记为垃圾的对象进行回收了。怎么样,简单吧。但是这种策略的缺点很明显,

回收后内存碎片很多,如果之后程序运行时申请大内存,可能会又导致一次GC。

虽然缺点明显,这种策略却是后两种策略的基础。正因为它的缺点,所以促成了

后两种策略的产生。


(2)标记-复制


将内存分为两块,标记完成开始回收时,将一块内存中保留的对象全部复制到另

一块空闲内存中。实现起来也很简单,当大部分对象都被回收时这种策略也很高效。

但这种策略也有缺点,可用内存变为一半了!


怎样解决呢?聪明的程序员们总是办法多过问题的。可以将堆不按1:1的比例分离,

而是按8:1:1分成一块Eden和两小块Survivor区,每次将Eden和Survivor中存活的对象

复制到另一块空闲的Survivor中。这三块区域并不是堆的全部,而是构成了新生代


从下图可以看到这三块区域如何配合完成GC的,具体的对象空间分配以及晋升请

参加后面第6条补充。

为什么不是全部呢?如果回收时,空闲的那一小块Survivor不够用了怎么办?这就是

老年代的用处。当不够用时,这些对象将直接通过分配担保机制进入老年代。那么

老年代也使用标记-复制策略吧?当然不行!老年代中的对象可不像新生代中的,

每次回收都会清除掉大部分。如果贸然采用复制的策略,老年代的回收效率可想而知。

(3)标记-整理

根据老年代的特点,采用回收掉垃圾对象后对内存进行整理的策略再合适不过,将

所有存活下来的对象都向一端移动。

4.实现:虚拟机中的收集器

(1)新生代上的GC实现

Serial:单线程的收集器,只使用一个线程进行收集,并且收集时会暂停其他所有

工作线程(Stop the world)。它是Client模式下的默认新生代收集器。

ParNew:Serial收集器的多线程版本。在单CPU甚至两个CPU的环境下,由于线程

交互的开销,无法保证性能超越Serial收集器。

Parallel Scavenge:也是多线程收集器,与ParNew的区别是,它是吞吐量优先

收集器。吞吐量=运行用户代码时间/(运行用户代码+垃圾收集时间)。另一点区别

是配置-XX:+UseAdaptiveSizePolicy后,虚拟机会自动调整Eden/Survivor等参数来

提供用户所需的吞吐量。我们需要配置的就是内存大小-Xmx和吞吐量GCTimeRatio。

(2)老年代上的GC实现

Serial Old:Serial收集器的老年代版本。

Parallel Old:Parallel Scavenge的老年代版本。此前,如果新生代采用PS GC的话,

老年代只有Serial Old能与之配合。现在有了Parallel Old与之配合,可以在注重吞吐量

及CPU资源敏感的场合使用了。

CMS:采用的是标记-清除而非标记-整理,是一款并发低停顿的收集器。但是由于

采用标记-清除,内存碎片问题不可避免。可以使用-XX:CMSFullGCsBeforeCompaction

设置执行几次CMS回收后,跟着来一次内存碎片整理。

5.触发:何时开始GC?

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

回收新生代。而Full GC(老年代回收,一般伴随一次Minor GC)则有几种触发条件:

(1)老年代空间不足

(2)PermSpace空间不足

(3)统计得到的Minor GC晋升到老年代的平均大小大于老年代的剩余空间

这里注意一点:PermSpace并不等同于方法区,只不过是Hotspot JVM用PermSpace来

实现方法区而已,有些虚拟机没有PermSpace而用其他机制来实现方法区。

6.补充:对象的空间分配和晋升

(1)对象优先在Eden上分配

(2)大对象直接进入老年代

虚拟机提供了-XX:PretenureSizeThreshold参数,大于这个参数值的对象将直接分配到

老年代中。因为新生代采用的是标记-复制策略,在Eden中分配大对象将会导致Eden区

和两个Survivor区之间大量的内存拷贝。

(3)长期存活的对象将进入老年代

对象在Survivor区中每熬过一次Minor GC,年龄就增加1岁,当它的年龄增加到一定程度

(默认为15岁)时,就会晋升到老年代中。

发表于 2016-08-11 09:57:00 回复(17)

1.Serial New/Serial Old

    Serial/Serial Old收集器是最基本最古老的收集器,它是一个单线程收集器,并且在它进行垃圾收集时,必须暂停所有用户线程。Serial New收集器是针对新生代的收集器,采用的是Copying算法,Serial Old收集器是针对老年代的收集器,采用的是Mark-Compact算法。它的优点是实现简单高效,但是缺点是会给用户带来停顿。

2.Parallel New

    Parallel New收集器是Serial收集器的多线程版本(参照Serial New),使用多个线程进行垃圾收集。

3.Parallel Scavenge

    Parallel Scavenge收集器是一个新生代的多线程收集器(并行收集器),它在回收期间不需要暂停其他用户线程,其采用的是Copying算法,该收集器与前两个收集器有所不同,它主要是为了达到一个可控的吞吐量。

4.Parallel Old

    Parallel Old是Parallel Scavenge收集器的老年代版本(并行收集器),使用多线程和Mark-Compact算法。

5.CMS

    CMS(Current Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器,它是一种并发收集器,采用的是Mark-Sweep算法。

6.G1

    G1收集器是当今收集器技术发展最前沿的成果,它是一款面向服务端应用的收集器,它能充分利用多CPU、多核环境。因此它是一款并行与并发收集器,并且它能建立可预测的停顿时间模型。

编辑于 2015-11-07 22:22:43 回复(4)
我现在回家种田还来得及?
发表于 2018-01-24 22:23:52 回复(1)
答案AD
新生代串行收集/并行回收器:复制算法;
老年代串行收集/并行回收器:标记-压缩算法;
并行收集器:将串行收集器多线程化,回收策略和串行收集器一致,因此该收集器是新生代为复制算法,老年代为标记-压缩算法。
CMS收集器:Concurrent Mark Sweep,从名字就能知道使用的是多线程的标记-清除算法。
发表于 2016-08-09 21:21:19 回复(1)

编辑于 2019-10-21 21:33:20 回复(0)
新生代垃圾回收器和老年代垃圾回收器都有哪些?有什么 区别?
    新生代回收器:Serial、ParNew、Parallel Scavenge
    老年代回收器:Serial Old、Parallel Old、CMS
    整堆回收器:G1
新生代垃圾回收器一般采用的是复制算法,复制算法的优点是效率高,缺点是内 存利用率低;
老年代回收器一般采用的是标记-整理的算法进行垃圾回收
发表于 2022-01-25 13:35:52 回复(0)
在垃圾的分代回收机制中:
    新生代一般采用“复制”算法:因为新生代每次都有大批量对象死去,就以少量对象的复制成本完成收集
    老年代一般采用“标记-整理/清除”算法:因为对象存活率高,且没有额外内存,故采用“标记-整理”或者“标记-清除”
发表于 2018-02-25 16:21:17 回复(0)
上面新生代对应的是复制算法,下面老年代一般是标记整理算法,CMS使用的是标记清除算法
这个题目做了两次都错了  
如果C说的并行收集器分为ParNew和Parallel Old两部分,那确实是错了,但是一直每太懂这个并行收集器到底是这两者的综合呢还是单指ParNew
发表于 2016-08-10 21:47:54 回复(0)
并行收集器是工作在新生代中的是单线程变成多线程。与新生代一样是复制回收算法。
新生的并行与串行回收器都是使用复制回收算法
发表于 2015-11-23 16:48:26 回复(1)
答案ACD
           参见博文:http://zm6.sm-img2.com/?src=http%3A%2F%2Fwww.educity.cn%2Fjava%2F505862.html&uid=b01a06fcb5bab417e57d24d2201f8915&hid=&restype=1&from=derive&depth=2&query=&uc_param_str=&link_type=12
发表于 2015-11-07 10:40:44 回复(0)
新生代基本采用复制算法
老年代采用标记整理算法
cms采用标记清理
发表于 2022-04-04 21:34:04 回复(0)
看到本题知识点,我就知道这题不简单
发表于 2020-03-05 12:26:39 回复(1)
两个最基本的java回收算法:复制算法和标记清理算法
复制算法:两个区域A和B,初始对象在A,继续存活的对象被转移到B。此为新生代最常用的算法
标记清理:一块区域,标记可达对象(可达性分析),然后回收不可达对象,会出现碎片,那么引出
标记-整理算法:多了碎片整理,整理出更大的内存放更大的对象
两个概念:新生代和年老代
新生代:初始对象,生命周期短的
永久代:长时间存在的对象
整个java的垃圾回收是新生代和年老代的协作,这种叫做分代回收。
P.S:Serial New收集器是针对新生代的收集器,采用的是复制算法
Parallel New(并行)收集器,新生代采用复制算法,老年代采用标记整理
Parallel Scavenge(并行)收集器,针对新生代,采用复制收集算法
Serial Old(串行)收集器,新生代采用复制,老年代采用标记整理
Parallel Old(并行)收集器,针对老年代,标记整理
CMS收集器,基于标记清理
G1收集器:整体上是基于标记 整理 ,局部采用复制

综上:新生代基本采用复制算法,老年代采用标记整理算法。cms采用标记清理。
发表于 2018-10-17 16:59:33 回复(0)
我居然成功蒙对了
发表于 2018-10-17 16:22:26 回复(0)