JVM垃圾回收算法(最全)
JVM垃圾回收算法(最全) 下面是JVM虚拟机运行时的内存模型: 1.方法区 Perm(永久代、非堆) 2.虚拟机栈 3.本地方法栈 (Native方法) 4.堆 5.程序计数器 1 首先的问题是:jvm如何知道那些对象需要回收 ?目前两种标识算法、三种回收算法、两种清除算法、三种收集器
在root搜索算法的里面,我们说的引用这里都指定的是强引用关系。所谓强引用关系,就是通过用new 方式创建的对象,并且显示关联的对象 [java]?
?
以上就是代表的是强引用关系,变量obj 强引用了 Object的一个对象。 java里面有四种应用关系,从强到弱分别为: Strong Reference(强引用) –>Weak Reference (弱引用) -> Soft Reference(软引用) – > Phantom Reference(引用) Strong Reference : 只有在引用对象root不可达的情况下才会标识为可回收,垃圾回收才可能进行回收 Weak Reference :即使在root算法中 其引用的对象root可达到,但是如果jvm堆内存 不够的时候,还是会被回收。 Soft Reference : 无论其引用的对象是否root可达,在响应内存需要时,由垃圾回收判断是否需要回收。 Phantom Reference :在回收器确定其指示对象可另外回收之后,被加入垃圾回收队列.
由于现在的处理器都是多核的,处理器的性能得到了极大的提升,所以在此基础上有产生了几种垃圾收集算法。主要包括两种算法
以上几种算法是垃圾回收的基本算法,jvm垃圾回收就是在以上几种算法为基础的,在以上几种算法的基础上,java垃圾回收器可以分为以下几种:
串行处理器: --适用情况:数据量比较小(100M左右);单处理器下并且对响应时间无要求的应用。 --缺点:只能用于小型应用 并行处理器: --适用情况:“对吞吐量有高要求”,多CPU、对应用响应时间无要求的中、大型应用。举例:后台处理、科学计算。 --缺点:垃圾收集过程中应用响应时间可能加长 并发处理器: --适用情况:“对响应时间有高要求”,多CPU、对应用响应时间有较高要求的中、大型应用。举例:Web服务器/应用服务器、电信交换、集成开发环境。 JDK5.0适用的分代垃圾回收算法?????? 分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率。 ?????? 在Java程序运行的过程中,会产生大量的对象,其中有些对象是与业务信息相关,比如Http请求中的Session对象、线程、Socket连接,这类对象跟业务直接挂钩,因此生命周期比较长。但是还有一些对象,主要是程序运行过程中生成的临时变量,这些对象生命周期会比较短,比如:String对象,由于其不变类的特性,系统会产生大量的这些对象,有些对象甚至只用一次即可回收。 ?????? 试想,在不进行对象存活时间区分的情况下,每次垃圾回收都是对整个堆空间进行回收,花费时间相对会长,同时,因为每次回收都需要遍历所有存活对象,但实际上,对于生命周期长的对象而言,这种遍历是没有效果的,因为可能进行了很多次遍历,但是他们依旧存在。因此,分代垃圾回收采用分治的思想,进行代的划分,把不同生命周期的对象放在不同代上,不同代上采用最适合它的垃圾回收方式进行回收。 如何分代 如图所示: ?????? 虚拟机中的共划分为三个代:年轻代(Young Generation)、年老点(Old Generation)和持久代(Permanent Generation)。其中持久代主要存放的是Java类的类信息,与垃圾收集要收集的Java对象关系不大。年轻代和年老代的划分是对垃圾收集影响比较大的。 年轻代: ????? 所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。年轻代分三个区。一个Eden区,两个Survivor区(一般而言)。大部分对象在Eden区中生成。当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor去也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制“年老区(Tenured)”。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来 对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor去过来的对象。而且,Survivor区总有一个是空的。同时,根据程序需要,Survivor区是可以配置为多个的(多于两个),这样可以增加对象在年轻代中的存在时间,减少被放到年老代的可能。 年老代: ????? 在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。 持久代: ????? 用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,例如Hibernate等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过-XX:MaxPermSize=<N>进行设置。 什么情况下触发垃圾回收 由于对象进行了分代处理,因此垃圾回收区域、时间也不一样。GC有两种类型:Scavenge GC和Full GC。 (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回收后,跟着来一次内存碎片整理。
GC类型?GC有两种类型:Scavenge GC和Full GC。?1. Scavenge GC?一般情况下,当新对象生成,并且在Eden申请空间失败时,就好触发Scavenge GC,堆Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。?2. Full GC?对整个堆进行整理,包括Young、Tenured和Perm。Full GC比Scavenge GC要慢,因此应该尽可能减少Full GC。有如下原因可能导致Full GC:?* Tenured被写满?* Perm域被写满?* System.gc()被显示调用?* 上一次GC之后Heap的各域分配策略动态变化?
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- SSM框架搭建图文教程(推荐)
- 异常:android.os.NetworkOnMainThreadException
- Javafx:使用鼠标在ImageView上绘图
- java – 如何基于InputStream创建iText BaseFont
- CentOS 7下JDK8的详细安装步骤
- java – SWT:如何进行高质量图像调整大小
- java – org.scribe.exceptions.OAuthException:响应正文不
- Main2Activity.java
- java – 加密和解密ArrayList
- java – Android:Snackbar给出了ArrayIndexOutOfBoundsExc