JVM内存模型
-
本地方法栈:加载nativ修饰的方法。(线程独享)
-
java栈(线程栈):存储8种基本类型的变量+对象的引用变量+实例方法,它的生命期是跟随线程的生命期。每个方法在栈中已栈帧的形式存在。(线程独享)
-
程序计数器:存储指向下一条指令的地址。(线程独享)
-
方法区(元空间):线程共享的运行时内存区域,存储了每一个类的结构信息,常量池字段和方法数据、构造函数和普通方法的字节码内容。(多个线程共享)
-
堆:一个JVM实例只存在一个堆内存,堆内存的大小是可以调节的。类加载器读取了类文件后,保存所有引用类型的真实信息,以方便执行器执行。(多个线程共享)
- java堆从GC的角度还可以分为:新生代(Eden区-伊甸区,From Survivor幸存0区,To Survivor幸存1区)和老年区
- 新生代占1/3,老年区占2/3
- 新生代中的伊甸区占8/10,幸存0区和1区各站1/10
- 首先,当Eden区满的时候会触发第一次GC,把还活着的对象拷贝到SurvivorFrom区,当Eden区再次触发GC的时候会扫描Eden区和From区域,对这两个区域进行垃圾回收,经过这次回收后还存活的对象,则直接复制到To区域(如果有对象的年龄已经达到了老年的标准,则赋值到老年代区),同时把这些对象的年龄+1
- 然后,清空Eden和SurvivorFrom中的对象,也即复制之后有交换,谁空谁是to
- 最后,SurvivorTo和SurvivorFrom互换,原SurvivorTo成为下一次GC时的SurvivorFrom区。部分对象会在From和To区域中复制来复制去,如此交换15次(由JVM参数决定-XX:MaxTenuringThreshold=15,这个参数默认是15),最终如果还是存活,就存入到老年代
- 如果分配的新对象比较大Eden区放不下但Old区可以放下时,对象会被直接分配到Old区(即没有晋升这一过程,直接到老年代了)
提别注意当老年区或者元空间满了会发生full gc,如果还是放不下的时候会发生java.lang.OutOfMemoryError: Java heap space异常
full gc过程的时候会发生STW(停止工作线程),所以我们的程序中要尽量减少full gc的次数
Survivor的存在意义就是减少被送到老年代的对象,设置两个Survivor区最大的好处就是解决内存碎片化。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY