性能优化|一张图带你了解JVM是如何进行内存分配

对象优先在新生代分配

  • 如果对象能够在eden区分配,那么就直接在eden区分配
  • 如果eden区域大小不够新对象存储的话,则会触发一次minor gc,
  • 如果minor gc后发现对象也无法在s区分配,则会直接在老年代中分配
  • 如果老年代也无法存储,则会触发full gc

什么情况下,对象会直接在老年代中分配?

  • 大对象会直接进入老年代
    什么叫做大对象呢,这个是由我们配置的参数决定的
    -XX:PretenureSizeThreshold=xxx
    如果新分配的对象超过这个值,就会直接在老年代中分配对象,这样做的目的是减小大对象来回复制带来的gc 时间损耗,需要注意的是这个参数只在serial和parNew两种收集器下生效

  • 长期存活的对象会直接进入老年代

    • 如何判对对象是长期存活的?
      虚拟机会给每个对象的头部分配一个字段,记录对象的年龄,年龄默认为1,在经历一次minor gc之后,如果对象还存活,则将年龄加1;

    • 如果对象的年龄达到了 -XX:MaxTenuringThreshold参数配置的值,默认为15,则会直接进入老年代

  • 动态年龄判断,决定是否进入老年代
    动态年龄判断是在minor gc之后出发的。
    在每次minor gc之后,会按照年龄大小进行排序,从年龄小的开始累加内存空间,如果累加到年龄为10的对象的时候,内存空间已经超过了s区的50%,这个时候就会把大于年龄10的存活对象全部移动老年代中;

  • minor gc之后,s区放不下,会直接移动到老年代中

什么叫空间分配担保机制?

jvm在每次minor gc之前,都会计算老年代的剩余可用空间,如果可用空间小于年轻代里面所有对象之和,如果没有配置担保参数(“-XX:-HandlePromotionFailure),这个时候就会直接执行full gc,如果配置了担保参数,就不会立即发生full gc,这个时候需要判断老年代可用空间是否大于之前每次minor gc后移动到老年代的平均大小,如果大于,则还是执行minor gc,否则执行 full gc ,流程图如下:
在这里插入图片描述

如何判断对象是否被回收

  • 引用计数法
    给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加1;当引用 失效,计数器就减1;任何时候计数器为0的对象就是不可能再被使用的。
    这个方法实现简单,效率高,但是目前主流的虚拟机中并没有选择这个算法来管 理内存,其最主要的原因是它很难解决对象之间相互循环引用的问题

  • 可达性分析算法
    这个算法的基本思想就是通过一系列的称为 “GC Roots” 的对象作为起点, 从这些节点开始向下搜索,找到的对象都标记为非垃圾对象,其余未标记的对象 都是垃圾对象 GC Roots根节点:线程栈的本地变量、静态变量、本地方法栈的变量等等

微信搜一搜【AI码师】关注帅气的我,回复【干货领取】,将会有大量面试资料和架构师必看书籍等你挑选,包括java基础、java并发、微服务、中间件等更多资料等你来取哦。

猜你喜欢

转载自blog.csdn.net/weixin_34311210/article/details/109438842