一、为什么要分代

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

在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区是可以配置为多个的(多于两个),这样可以增加对象在年轻代中的存在时间,减少被放到年老代的可能。

新生代有划分为Eden、From Survivor和To Survivor三个部分,他们对应的内存空间的大小比例为8:1:1,也就是,为对象分配内存的时候,首先使用Eden空间,经过GC后,没有被回收的会首先进入From Survivor区域,任何时候,都会保持一个Survivorq区域(From Survivor或To Survivor)完全空闲,也就是说新生代的内存利用率最大为90%。From Survivor和To Survivor两个区域会根据GC的实际情况,进行互换,将From Survivor区域中的对象全部复制到To Survivor区域中,或者反过来,将To Survivor区域中的对象全部复制到From Survivor区域中。

年老代:

在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。

GC过程中,当某些对象经过多次GC都没有被回收,可能会进入到年老代。或者,当新生代没有足够的空间来为对象分配内存时,可能会直接在年老代进行分配。

持久代:

用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,例如Hibernate等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过-XX:MaxPermSize=<N>进行设置。

永久代实际上对应着虚拟机运行时数据区的“方法区”,这里主要存放类信息、静态变量、常量等数据。一般情况下,永久代中对应的对象的GC效率非常低,因为这里的的大部分对象在运行都不要进行GC,它们会一直被利用,直到JVM退出。

三、什么情况下触发垃圾回收

由于对象进行了分代处理,因此垃圾回收区域、时间也不一样。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的各域分配策略动态变化

以上便是Java虚拟机JVM:分代垃圾回收策略的基本概念以及过程的全部内容。

希望对大家的编程之路有所帮助。

可以的话请支持一下小编哦,谢谢。

JVM | 分代垃圾回收策略的基本概念以及过程的更多相关文章

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

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

  2. 【java虚拟机】分代垃圾回收策略的基础概念

    作者:平凡希 原文地址:https://www.cnblogs.com/xiaoxi/p/6602166.html 一.为什么要分代 分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一 ...

  3. Java中的分代垃圾回收策略

    一.分代GC的理论基础 分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的.因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率. 在Java程序运行的过程中,会产生大 ...

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

    为什么要分代 分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的.因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率. 在Java程序运行的过程中,会产生大量的对象, ...

  5. JVM调优总结:分代垃圾回收详述

    为什么要分代 分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的.因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率. 在Java程序运行的过程中,会产生大量的对象, ...

  6. java虚拟机学习-JVM调优总结-分代垃圾回收详述(9)

    为什么要分代 分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的.因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率. 在Java程序运行的过程中,会产生大量的对象, ...

  7. JVM堆内存控制/分代垃圾回收

    JVM的堆的内存, 是通过下面面两个参数控制的 -Xms 最小堆的大小, 也就是当你的虚拟机启动后, 就会分配这么大的堆内存给你 -Xmx 是最大堆的大小 当最小堆占满后,会尝试进行GC,如果GC之后 ...

  8. JVM调优总结(4):分代垃圾回收

    为什么要分代 分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的.因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率. 在Java程序运行的过程中,会产生大量的对象, ...

  9. JVM调优总结(三)——分代垃圾回收详述

    为什么要分代 分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的.因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率. 在Java程序运行的过程中,会产生大量的对象, ...

随机推荐

  1. 解决maven 引用JDK内部类编译错误 程序包:com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler不存在

    当maven项目里面有用到JDK内部的一些类或者接口的时候,用maven编译一般会出现如下错误: 程序包:com.sun.xml.internal.bind.marshaller.CharacterE ...

  2. 解决Django项目静态资源无法访问的问题

    静态资源无法访问 url.py中配置 from django.conf.urls import url from django.views import static from django.conf ...

  3. (6)python基础数据类型

    python的六大标准数据类型 (一)Number   数字类型(int float bool complex) (二)String 字符串类型 (三)List 列表类型 (四)Tuple 元组类型 ...

  4. 通过快捷方式lnk获得文件真实路径

    通过快捷方式.lnk获得文件真实路径前提最近开发资源管理,需要预先上传大量资源,负责整理资源的同学因为空间不足,直接用快捷键方式整理视频资源OTZ,所以只能想办法通过.lnk文件获得文件的真实地址. ...

  5. 关于SendMessage和PostMessage的理解的例子

    对于SendMessage 和 PostMessage 平时口头的解释是 SendMessage 发送消息后等待返回, PostMessage 发送消息后立即返回 . 但是这样解释还是不具体,什么叫等 ...

  6. python_模块1

    1.将指定的字符串进行加密 # 导入模块 import hashlib def get_md5(data): # 获取hashlib模块中的md5加密算法 obj = hashlib.md5() # ...

  7. RHEL8 创建本地YUM存储库

    yum 的好处及本地yum的好处不在本文讨论范畴,本文针对rhel8中的新功能yum做简要介绍和配置,在 RHEL 8中分为两个存储库: BaseOS 应用程序流(AppStream) BaseOS中 ...

  8. bzoj3993: [SDOI2015]星际战争(二分+最大流)

    题目描述 3333年,在银河系的某星球上,X军团和Y军团正在激烈地作战. 在战斗的某一阶段,Y军团一共派遣了N个巨型机器人进攻X军团的阵地,其中第i个巨型机器人的装甲值为Ai.当一个巨型机器人的装甲值 ...

  9. oracle split函数

    PL/SQL 中没有split函数,需要自己写. 代码: ); --创建一个 type ,如果为了使split函数具有通用性,请将其size 设大些. --创建function create or r ...

  10. mysql关于索引的一些零碎知识点(持续更新)

    1.is null可以使用索引(网上很多文章存在误导,这个确实可以使用索引),is not null无法使用索引. 2.为什么重复数据较多的列不适合使用索引? 假如索引列TYPE有5个键值,如果有1万 ...