JVM内存分配以及回收机制

写在开头

基本定义

在开始梳理内存分配规则之前,还是需要先强调一下JVM的的两种垃圾回收机制(因为jvm很多内存机制也是为了保证gc 触发的合理性设计的):

  1. minor gc:即新生代内存垃圾回收,执行频率较高,而且执行速度快,对系统性能影响较小
  2. full gc:此回收方式会回收 老年代、新生代、方法区三块内存区域的垃圾,因为扫描的区域的,因此效率比较低下

JVM内存分配

  • 对象优先被分配在eden区:在绝大多数情况下,我们new 一个对象的时候,会在新生代的eden区分配一块内存空间,不过当新生代的剩余内存空间不足以存储新创建的对象时,新创建的对象会被发起一次minor gc,minor gc后,如果发现survivor区空间不足以存储eden区的对象,会直接将当前eden区的对象直接转移至老年代,下图即参考示例代码
  • 当新生代空间不足时,所有新生代对象直接移入老年代

  • 大对象内存分配规则: 当 需要大量连续空间的对象 需要在堆空间进行内存分配时,jvm会判断大对象占用内存是否超过设置的大对象阈值,如果超过大对象阈值,则此对象会直接分配至老年代。大对象阈值可以通过 XX😛retenureSizeThreshold 进行设置,在我们实际的业务系统中,我们可以根据业务的需要动态地调整此值,以减少minor gc的次数,提升性能。
  • 根据对象年龄分配内存:之前的文章讲到过,如果一个对象经历了15次minor gc后,仍未被回收,则会被移入老年代。其实15次只是jvm的一个默认配置,对象的年龄阈值可以通过 –XX:MaxTenuringThreshold 参数进行配置
  • 较大年龄分配规则:当survivor区中如果存在某些对象的大小合计超过50%,JVM会开始查找survivor区中年龄最大的对象,移入老年代,如果,年龄最大的对象移入老年代后,内存占用仍超过50%,则将剩余对象中年龄最大的对象移入老年代,循环往复,直至survivor区内存空间占用小于50%,效果如下图:
  • survivor将对象直接移入老年代

  • 老年代内存不足重新触发minor gc机制(即担保机制):当老年代剩余空间小于新生代所有对象大小( 错垃圾对象)时,jvm会自动触发一次minor gc,执行完minor gc后会计算当前新生代所有对象大小是否小于每次minor gc后进入老年代时对象的平均大小,如果小于,则直接将对象移入老年代,如果大于,则会触发full gc(注意此机制在jdk 1.8默认开启,之前的版本需要通过-XX:-HandlePromotionFailure 配置手动开启)
  • JVM对象回收机制

    上面讲了JVM如何进行内存分配,那上文中多次提到的gc过程中,JVM又是如何识别出当前对象为垃圾对象,可以执行回收操作呢?其实JVM判断对象是否回收有两种方法:

    1. 引用计数法(目前我们用到的主流虚拟机未使用此方法):此方法的原理就是如果某对象被引用了,则当前对象的计数器+1,当当前对象的计数器指数为0时,代表此对象已不在可能被使用,可以被回收。不过此方法无法解决对象互相依赖的问题,会导致大量对象无法回收,所以目前很少被使用
    2. 可达性分析算法:此算法的核心思想是所有的有效对象都必须存在”GC Root”作为起点,即JVM会标记所有的GC ROOT以及其所有的子节点 为非垃圾对象,JVM在进行GC时,只要没有被标记为非垃圾对象的对象,都属于垃圾对象,将其进行回收
      1. 此处解释一下什么是GCRoot节点,比如线程栈的本地变量、静态变量等

    JVM常见的引用类型

    1. 强引用:我们写的业务代码中,例如 User user = new User() 这种就属于强引用
    2. 软引用:软引用需要使用SoftReference 进行声明 例如下面这种形式, 弱引用的优势在于,当jvm堆的新生代或者老年代区域不足时,会优先回收软引用的内存对象,软引用主要应用于”需要提高系统使用性能,且当前对象又不是系统必要业务对象,内存不足时可先回收掉,后续重新加载即可”的业务场景中,例如非关键数据的缓存
      1. SoftReference<User> user = new SoftReference<User>(new User())
    3. 弱引用:弱引用的对象在进行gc时就会被回收掉,应用场景非常少,个人没用过
    4. 虚引用:没用过,也没听到什么使用场景,有兴趣了解可以百度

    方法区内存回收机制

    方法区主要是回收不会在被使用的类元信息,判定某类不被使用需要满足三个条件:

    1. 所有的实例对象需要被回收,即new出来的对象需要被回收
    2. 该类的classloader被回收
    3. 该类的class对象也需要被回收

    以上就是JVM内存分配机制以及回收机制的所有内容了,后面分析的是JVM垃圾回收算法和垃圾收集器了~

    声明:本站部分文章内容及图片转载于互联 、内容不代表本站观点,如有内容涉及侵权,请您立即联系本站处理,非常感谢!

    (0)
    上一篇 2021年3月1日
    下一篇 2021年3月1日

    相关推荐