05_JVM 分代模型:年轻代、老年代、永久代
1016字约3分钟
2024-08-10
大部分对象的存活周期都很短
public class Order {
public static void main(String[] args) {
while (true) {
loadMessageFromDisk();
}
}
public static void loadMessageFromDisk() {
MqManager mqManager = new MqManager();
mqManager.load();
}
}
上面代码中,每一次的 while
循环,执行完 loadMessageFromDisk()
方法就会出栈,就会有一个新的 MqManager
对象没有被引用,然后被垃圾回收掉,释放掉 Java堆内存
里的 MqManager
对象,如下图所示
像这里的 MqManager
对象就属于短暂存活的对象,这种对象在我们的代码中占到很大比例
少数对象是长期存活的
public class Order {
private static MqManager mqManager = new MqManager();
public static void main(String[] args) {
while (true) {
loadMessageFromDisk();
}
}
public static void loadMessageFromDisk() {
mqManager.load();
}
}
上面代码中,Order
类是在方法区里的,给 Order
这个类定义一个 mqManager
静态变量,让 mqManager
引用一个在 Java堆内存
里创建的 MqManager
实例对象
在 while
循环里,MqManager
这个实例对象,会一直被 Order
的静态变量引用,周期性的调用 load()
方法,然后就会一直驻留在 Java堆内存
中,不会被垃圾回收掉
那么类似这种被类的静态变量长期引用的对象,他需要长期留在 Java堆内存
里,这种对象就是生命周期很长的对象
年轻代和老年代
JVM
将 Java堆内存
划分为了两个区域:年轻代、老年代
年轻代:存放创建和使用完之后立马就要回收的对象,即存活周期短
老年代:存放创建之后需要长期存在的对象,即存活周期长
public class Order {
private static MqConsumer mqConsumer = new MqConsumer();
public static void main(String[] args) {
loadMessageFromDisk();
while (true) {
mqConsume();
}
}
public static void loadMessageFromDisk() {
MqManager mqManager = new MqManager();
mqManager.load();
}
public static void mqConsume() {
mqConsumer.consume();
}
}
Order
类的静态变量 mqConsumer
引用了 MqConsumer
对象,这是长期需要驻留在内存里使用的,这个对象会在年轻代里停留一会,最终进入老年代,如下图
main()
方法执行时,先调用 loadMessageFromDisk()
方法,这个方法中创建了一个 MqManager
对象,这个对象是放在年轻代里,由栈帧里的局部变量 mqManager
来引用
当 loadMessageFromDisk()
方法执行完毕,方法的栈帧就会出栈,对应的年轻代里的 MqManager
对象就会被回收掉
接着执行的 while
循环代码,周期性的调用 MqConsumer
的 consume()
方法,MqConsumer
这个对象被 Order
类的静态变量 mqConsumer
引用,且持续的使用,他会长期存在于老年代里
为什么要分成年轻代和老年代
这和垃圾回收有关,对于年轻代里的对象,他们的特点是创建之后很快会被回收,所以需要一种垃圾回收算法
对于老年代里的对象,他们的特点是长期存在,所以需要另外一种垃圾回收算法,所以需要分成两个区域来存放不同的对象
什么是永久代
JVM
里的永久代是我们提到过的方法区,可以认为永久代就是存放一些类信息的
思考环节
1、每个线程都有 Java虚拟机栈
,里面也有方法的局部变量等数据,那么 Java虚拟机栈
需要进行垃圾回收吗?
JVM
里垃圾回收针对的是年轻代、老年代、方法区(永久代),不会针对方法的栈帧,方法一旦执行完毕,栈帧出栈,里面的局部变量就直接从内存里清掉了