zoukankan      html  css  js  c++  java
  • 007-对象内存分配与回收,垃圾收集过程

    一、概述

    1.1、图解

                    

      默认的,新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 ),即:新生代 ( Young ) = 1/3 的堆空间大小。老年代 ( Old ) = 2/3 的堆空间大小。

      其中,新生代 ( Young ) 被细分为 Eden 和 两个 Survivor 区域,这两个 Survivor 区域分别被命名为 from 和 to,以示区分。默认的,Eden : from : to = 8 : 1 : 1 ( 可以通过参数 –XX:SurvivorRatio 来设定 ),即: Eden = 8/10 的新生代空间大小,from = to = 1/10 的新生代空间大小。JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务,所以无论什么时候,总是有一块 Survivor 区域是空闲着的。因此,新生代实际可用的内存空间为 9/10 ( 即90% )的新生代空间。

    JVM堆内存分为2块:Permanent Space 和 Heap Space。

    • Permanent 即 持久代(Permanent Generation),主要存放的是Java类定义信息,与垃圾收集器要收集的Java对象关系不大。

    • Heap = { Old + NEW = {Eden, from, to} },Old 即 年老代(Old Generation),New 即 年轻代(Young Generation)。年老代和年轻代的划分对垃圾收集影响比较大。

    1.2、为什么会有年轻代

      分代的唯一理由就是优化GC性能。如果没有分代,那所有的对象都在一块,GC的时候要找到哪些对象没用,这样就会对堆的所有区域进行扫描。而我们的很多对象都是朝生夕死的,如果分代的话,我们把新创建的对象放到某一地方,当GC的时候先把这块存“朝生夕死”对象的区域进行回收,这样就会腾出很大的空间出来。  

    1.3、对象分配过程

    1》 对象优先在Eden上分配

      大多数情况下,对象优先在新生代Eden区域中分配。当Eden内存区域没有足够的空间进行分配时,虚拟机将触发一次 Minor GC(新生代GC)。Minor GC期间虚拟机将Eden区域的对象移动到其中一块Survivor区域。

      年轻代中的对象基本都是朝生夕死的(80%以上),所以在年轻代的垃圾回收算法使用的是复制算法,复制算法的基本思想就是将内存分为两块,每次只用其中一块,当这一块内存用完,就将还活着的对象复制到另外一块上面。复制算法不会产生内存碎片。

      在GC开始的时候,对象只会存在于Eden区和名为“From”的Survivor区,Survivor区“To”是空的。紧接着进行GC,Eden区中所有存活的对象都会被复制到“To”,而在“From”区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值(年龄阈值,可以通过-XX:MaxTenuringThreshold来设置)的对象会被移动到年老代中,没有达到阈值的对象会被复制到“To”区域。经过这次GC后,Eden区和From区已经被清空。这个时候,“From”和“To”会交换他们的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎样,都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程,直到“To”区被填满,“To”区被填满之后,会将所有对象移动到年老代中。

      

    2》大对象直接进入老年代

      所谓大对象是指需要大量连续空间的对象。虚拟机提供了一个XX:PretenureSizeThreshold参数,令大于这个值的对象直接在老年代中分配。

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

      虚拟机采用分代收集的思想管理内存,那内存回收时就必须能识别那些对象该放到新生代,那些该到老年代中。为了做到这点,虚拟机为每个对象定义了一个对象年龄Age,每经过一次新生代GC后任然存活,将对象的年龄Age增加1岁,当年龄到一定程度(默认为15)时,将会被晋升到老年代中,对象晋升老年代的年龄限定值,可通过-XX:MaxTenuringThreshold来设置。

    1.4、Minor GC 和Full GC区别

      新生代GC(Minor GC):指发生在新生代的垃圾收集动作,因为对象大多都具备朝生夕灭特性,所以Minor GC非常频繁,回收速度也比较快。

      老年代GC(Major GC / Full GC):指发生在老年代中的GC,出现Major GC后,经常会伴随至少一次的 Minor GC。Major GC的速度一般会比Minor GC慢10倍以上。

    1.5、有关年轻代的JVM参数

    1)-XX:NewSize和-XX:MaxNewSize

    用于设置年轻代的大小,建议设为整个堆大小的1/3或者1/4,两个值设为一样大。

    2)-XX:SurvivorRatio

    用于设置Eden和其中一个Survivor的比值,这个值也比较重要。

    3)-XX:+PrintTenuringDistribution

    这个参数用于显示每次Minor GC时Survivor区中各个年龄段的对象的大小。

    4).-XX:InitialTenuringThreshol和-XX:MaxTenuringThreshold

    用于设置晋升到老年代的对象年龄的最小值和最大值,每个对象在坚持过一次Minor GC之后,年龄就加1。

     5)、-Xmn,-XX:NewSize/-XX:MaxNewSize,-XX:NewRatio 3组参数都可以影响年轻代的大小,混合使用的情况下,优先级是什么?

    如下:

    1. 高优先级:-XX:NewSize/-XX:MaxNewSize 

    2. 中优先级:-Xmn(默认等效  -Xmn=-XX:NewSize=-XX:MaxNewSize=?) 

    3. 低优先级:-XX:NewRatio 

    推荐使用-Xmn参数,原因是这个参数简洁,相当于一次设定 NewSize/MaxNewSIze,而且两者相等,适用于生产环境。-Xmn 配合 -Xms/-Xmx,即可将堆内存布局完成。

    -Xmn参数是在JDK 1.4 开始支持。

  • 相关阅读:
    Spring Boot项目配置RabbitMQ集群
    rabbitMQ第二篇:java简单的实现RabbitMQ
    SpringBoot启动和停止脚步
    SpringBoot实战之SpringBoot自动配置原理
    maven profile 多环境
    Mybatis根据配置文件获取session(多数据源)
    Mybatis的mapper注册
    MyBatis SqlSessionFactory的几种常见创建方式
    Result映射成对象和List
    JAVA反射的使用之ResultSet的自动转换
  • 原文地址:https://www.cnblogs.com/bjlhx/p/8878536.html
Copyright © 2011-2022 走看看