JVM分代垃圾回收策略的基础概念

由于不同对象的生命周期不一样,因此在JVM的垃圾回收策略中有分代这一策略。本文介绍了分代策略的目标,如何分代,以及垃圾回收的触发因素。

  文章总结了JVM垃圾回收策略为什么要分代,如何分代,以及垃圾回收的触发因素。

  为什么要分代

  分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率。

  在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=进行设置。

  什么情况下触发垃圾回收

  由于对象进行了分代处理,因此垃圾回收区域、时间也不一样。GC有两种类型:Scavenge GC和Full GC。

  Scavenge GC

  一般情况下,当新对象生成,并且在Eden申请空间失败时,就会触发Scavenge GC,对Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。这种方式的GC是对年轻代的Eden区进行,不会影响到年老代。因为大部分对象都是从Eden区开始的,同时Eden区不会分配的很大,所以Eden区的GC会频繁进行。因而,一般在这里需要使用速度快、效率高的算法,使Eden去能尽快空闲出来。

  对整个堆进行整理,包括Young、Tenured和Perm。Full GC因为需要对整个对进行回收,所以比Scavenge GC要慢,因此应该尽可能减少Full GC的次数。在对JVM调优的过程中,很大一部分工作就是对于FullGC的调节。有如下原因可能导致Full GC:

  ◆ 年老代(Tenured)被写满

  ◆ 持久代(Perm)被写满

  ◆ System.gc()被显示调用

  ◆ 上一次GC之后Heap的各域分配策略动态变化

本文出自seven的测试人生公众号最新内容请见作者的GitHub页:http://qaseven.github.io/

时间: 2024-12-12 17:10:25

JVM分代垃圾回收策略的基础概念的相关文章

JVM分代垃圾回收机制关于New Generation为什么分为三个区域的疑问

问题描述 最近打算写一个分代垃圾回收,我打算在NewGeneration中分为两个区域,即只有from区域跟to区域,但是最近查看了好多关于JVM的分代垃圾机制的文章,JVM在NewGeneration中分为三个区域,即Eden.from.to三个区域,好多文章介绍Eden都是该区域是一整块连续的堆,加速了分配的速度,但是我想问的是,如果只分为两个区域,每次从from拷贝到to后,to区域剩下的空间也是连续的,分配速度应该也是很快的,这点让我很迷惑,为什么JVM要分为三个区域.所以,我想问一下我

JVM调优总结(五)-分代垃圾回收详述1

为什么要分代 分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的.因此,不同生命周期的对象可以采取不同的收集方式 ,以便提高回收效率. 在Java程序运行的过程中,会产生大量的对象,其中有些对象是与业务信息相关,比如Http请求中的Session对象.线程.Socket连接, 这类对象跟业务直接挂钩,因此生命周期比较长.但是还有一些对象,主要是程序运行过程中生成的临时变量,这些对象生命周期会比较短 ,比如:String对象,由于其不变类的特性,系统会产生大量的这些对象,有些对

JVM调优总结(六)-分代垃圾回收详述2

分代垃圾回收流程示意

浅谈jvm中的垃圾回收策略_java

java和C#中的内存的分配和释放都是由虚拟机自动管理的,此前我已经介绍了CLR中GC的对象回收方式,是基于代的内存回收策略,其实在java中,JVM的对象回收策略也是基于分代的思想.这样做的目的就是为了提高垃圾 回收的性能,避免对堆中的所有对象进行检查时所带来的程序的响应的延迟,因为jvm执行GC时,会stop the word,即终止其它线程的运行,等回收完毕,才恢复其它线程的操作.基于分代的思想是:jvm在每一次执行垃圾收集器时,只是对一小部分内存 对象引用进行检查,这一小部分对象的生命周

JVM 分代GC策略分析

我们以Sun HotSpot VM来进行分析,首先应该知道,如果我们没有指定任何GC策略的时候,JVM默认使用的GC策略.Java虚拟机是按照分代的方式来回收垃圾空间,我们应该知道,垃圾回收主要是针对堆(Heap)内存进行分代回收,将对内存可以分成新生代(Young Generation).年老代(Tenured Generation)和永久代(Permanent Generation)三个部分. 分代GC 分代GC包括如下三代: 新生代(Young Generation) 新生代有划分为Ede

JVM的内存分配与垃圾回收策略

自动内存管理机制主要解决了两个问题: 给对象分配内存以及回收分配给对象的内存. 垃圾回收的区域 前面的笔记中整理过虚拟机运行数据区,再看一下这个区域: 注意在这个Runtime Data Area中: 程序计数器.Java栈.本地方法栈3个区域随线程而生,随线程而灭: 每一个栈帧中分配多少内存基本上在类结构确定下来的时候就已知, 因此这几个区域的内存分配和回收都具有确定性,不需过多考虑回收问题,方法结束或者线程结束时,内存自然就随之回收了. Java堆和方法区Method Area则不一样, 一

深入理解JVM之三:垃圾回收算法

前言 垃圾收集算法是JVM中垃圾收集器的方法论,所以了解算法是必要的,在算法领域只做最简单的介绍,力求文章的简单易懂.垃圾收集算法主要有以下几种:标记-清除算法(mark-sweep).复制算法(copying)和标记-整理算法(mark-compact).随着jdk版本的升级,垃圾收集器也在不断的升级,现在最新的垃圾收集器已经能够对Java堆中一部分进行回收,也能够对Java堆中另一部分进行回收,这一成果在jdk1.7中得到体现.但是垃圾收集器的底层算法是深入垃圾收集器所必须了解的,这篇文章将

jvm 内存与垃圾回收

你对JVM内存组成结构和JVM垃圾回收机制是否熟悉,这里和大家简单分享一下,希望对你的学习有所帮助,首先来看一下JVM内存结构,它是由堆.栈.本地方法栈.方法区等部分组成,结构图如下所示. JVM学习笔记 JVM内存管理和JVM垃圾回收 JVM内存组成结构 JVM内存结构由堆.栈.本地方法栈.方法区等部分组成,结构图如下所示: 1)堆 所有通过new创建的对象的内存都在堆中分配,其大小可以通过-Xmx和-Xms来控制.堆被划分为新生代和旧生代,新生代又被进一步划分为Eden和Survivor区,

jvm 垃圾回收 分代-JVM垃圾回收关于New Generation为什么分为三个区域的疑问

问题描述 JVM垃圾回收关于New Generation为什么分为三个区域的疑问 最近打算写一个分代垃圾回收,我打算在New Generation中分为两个区域,即只有 from区域 跟 to区域,但是最近查看了好多关于JVM的分代垃圾机制的文章,JVM在New Generation中分为三个区域,即Eden.from.to三个区域,好多文章介绍Eden都是该区域是一整块连续的堆,加速了分配的速度,但是我想问的是,如果只分为两个区域,每次从from拷贝到to后,to区域剩下的空间也是连续的,分配