堆内存分代机制详解

tech2024-10-31  27

1.jvm的内存模型包括以下几部分: 方法区:是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据 Java堆:堆用来存储几乎所有对象、数组等都在此分配内存,在jvm内存中占的比很大,也是GC垃圾回收的主要地点 Java栈:当jvm在执行方法时,会在此区域中创建一个栈帧来存放方法的信息,比如返回值,局部变量表和各种对象引用等,方法开始执行前就先创建栈帧入栈,执行完后就出栈 本地方法栈:与Java栈类似,Java栈为虚拟机执行Java 方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native 方法服务 程序计数器:占用很小的一片区域,我们知道JVM执行代码是一行一行执行字节码,所以需要一个计数器来记录当前执行的行数 运行时常量池:是方法区的一部分,用于存放编译期生成的各种字面量和符号引用,在类加载后存放到方法区的运行时常量池中 在这里插入图片描述

2.jvm中Java堆的分代: jvm根据对象存活的周期不同,把堆内存划分为新生代、老年代和永久代

新生代: 新生成的对象优先存放在新生代中,新生代对象朝生夕死,存活率很低,在新生代中,常规应用进行一次垃圾收集一般可以回收70% ~ 95% 的空间,回收效率很高,新生代划分为三块,一块较大的Eden空间和两块较小的Survivor空间,采用复制算法来回收新生代 老生代:在新生代中经历了多次GC后仍然存活下来的对象会进入老年代中,老年代中的对象生命周期较长,存活率比较高,在老年代中进行GC的频率相对而言较低,而且回收的速度也比较慢 永久代:永久代储存类信息,常量,静态变量,即时编译器后的代码等数据,对这一区域而言,Java虚拟机规范指出可以不进行垃圾收集,一般而言不会进行垃圾回收 3.Java堆中新生代的垃圾回收机制: HotSpot将新生代划分为三块,一块较大的Eden空间和两块较小的Survivor空间,默认比例为8:1:1。划分的目的是因为HotSpot采用复制算法来回收新生代,设置这个比例是为了充分利用内存空间,减少浪费。新生成的对象在Eden区分配(大对象除外,大对象直接进入老年代),当Eden区没有足够的空间进行分配时,虚拟机将发起一次Minor GC。 GC开始时,对象只会存在于Eden区和From Survivor区,To Survivor区是空的(作为保留区域)。GC进行时,Eden区中所有存活的对象都会被复制到To Survivor区,而在From Survivor区中,仍存活的对象会根据它们的年龄值决定去向,年龄值达到年龄阀值(默认为15,新生代中的对象每熬过一轮垃圾回收,年龄值就加1,GC分代年龄存储在对象的header中)的对象会被移到老年代中,没有达到阀值的对象会被复制到To Survivor区。接着清空Eden区和From Survivor区,新生代中存活的对象都在To Survivor区。接着, From Survivor区和To Survivor区会交换它们的角色,也就是新的To Survivor区就是上次GC清空的From Survivor区,新的From Survivor区就是上次GC的To Survivor区,总之,不管怎样都会保证To Survivor区在一轮GC后是空的。GC时当To Survivor区没有足够的空间存放上一次新生代收集下来的存活对象时,需要依赖老年代进行分配担保,将这些对象存放在老年代中。

最新回复(0)