JVM内存模型

  • 本地方法栈:加载nativ修饰的方法。(线程独享)

  • java栈(线程栈):存储8种基本类型的变量+对象的引用变量+实例方法,它的生命期是跟随线程的生命期。每个方法在栈中已栈帧的形式存在。(线程独享)

  • 程序计数器:存储指向下一条指令的地址。(线程独享)

  • 方法区(元空间):线程共享的运行时内存区域,存储了每一个类的结构信息,常量池字段和方法数据、构造函数和普通方法的字节码内容。(多个线程共享)

  • 堆:一个JVM实例只存在一个堆内存,堆内存的大小是可以调节的。类加载器读取了类文件后,保存所有引用类型的真实信息,以方便执行器执行。(多个线程共享)

    • java堆从GC的角度还可以分为:新生代(Eden区-伊甸区,From Survivor幸存0区,To Survivor幸存1区)和老年区
    • 新生代占1/3,老年区占2/3
    • 新生代中的伊甸区占8/10,幸存0区和1区各站1/10
  1. 首先,当Eden区满的时候会触发第一次GC,把还活着的对象拷贝到SurvivorFrom区,当Eden区再次触发GC的时候会扫描Eden区和From区域,对这两个区域进行垃圾回收,经过这次回收后还存活的对象,则直接复制到To区域(如果有对象的年龄已经达到了老年的标准,则赋值到老年代区),同时把这些对象的年龄+1
  2. 然后,清空Eden和SurvivorFrom中的对象,也即复制之后有交换,谁空谁是to
  3. 最后,SurvivorTo和SurvivorFrom互换,原SurvivorTo成为下一次GC时的SurvivorFrom区。部分对象会在From和To区域中复制来复制去,如此交换15次(由JVM参数决定-XX:MaxTenuringThreshold=15,这个参数默认是15),最终如果还是存活,就存入到老年代
  4. 如果分配的新对象比较大Eden区放不下但Old区可以放下时,对象会被直接分配到Old区(即没有晋升这一过程,直接到老年代了)

提别注意当老年区或者元空间满了会发生full gc,如果还是放不下的时候会发生java.lang.OutOfMemoryError: Java heap space异常
full gc过程的时候会发生STW(停止工作线程),所以我们的程序中要尽量减少full gc的次数

Survivor的存在意义就是减少被送到老年代的对象,设置两个Survivor区最大的好处就是解决内存碎片化。

posted @   程序马2023  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示