- 年轻代
- 老年代
- 永久代
1.年轻代
年轻代,顾名思义,就是创建和使用完之后立马就把要回收的对象放在里面。一般对象第一次创建都会进入年轻代。如以下代码
public class ExamApp {
public static void main(String[] args) throws Exception{
while(true){
studentStudy();
Thread.sleep(1);
}
}
private static void studentStudy(){
Student student = new Student();
student.study();
}
}
首先一旦执行main()方法,那么就会把main()方法栈帧压入main线程的Java虚拟机栈;然后每次在while循环里,调用 studentStudy()方法,就会把studentStudy()方法的栈帧压入自己的Java虚拟机栈,在执行studentStudy()方法的时候,会在Java堆内存里会创建一个Student对象实例,而且studentStudy()方法的栈帧里会有 student
局部变量去引用Java堆内存里的 Student
对象实例。
在studentStudy 方法执行完毕之后,方法就结束了,studentStudy()栈帧就会出栈,此时 Student
就没人引用了,如果新生代我们预先分配的内存空间,几乎都被全部对象给占满了,这个时候,垃圾回收器就会触发一次新生代内存空间的垃圾回收,也称之为“Minor GC”,也称“Young GC”,它会尝试把新生代里那些没有人引用的垃圾对象,都给回收掉,释放内存空间。
然后继续执行 while
循环的时候,又会创建对象,分配内存空间,重复以上步骤。
所以,大部分对象都是存活周期极短的。
2.老年代
老年代呢,就是创建之后需要一直长期存在的对象放在里面。如以下代码:
public class ExamApp {
private static Student student = new Student();
public static void main(String[] args) throws Exception{
while(true){
studentStudy();
Thread.sleep(1);
}
}
private static void studentStudy(){
student.study();
}
}
ExamApp
类定义一个静态变量,也就是 student
,这个ExamApp
类是在JVM的方法区里的,然后让student
引用了一个在Java堆内存里创建的 Student
实例对象,如下图。
类似这种被类的静态变量长期引用的对象,需要长期停留在Java堆内存里,这种对象就是生存周期很长的对
象,它是轻易不会被垃圾回收的,需要长期存在,不停的去使用。
所以,少数对象是长期存活的。
3.永久代
JVM里的永久代其实就是我们之前说的方法区,其实所谓的永久代,可以认为永久代就是放一些类信息的。
4.总体结构
5.垃圾回收时机
-
年轻代什么时候进入老年代?
大部分的正常对象,优先在新生代分配内存的;
新生代如果对象满了,会触发Young GC回收掉没有人引用的垃圾对象;
如果有对象躲过了十多次垃圾回收,就会放入老年代里。 -
老年代什么时候进行垃圾回收?
如果老年代内存满了,就会触发垃圾回收,把老年代里没人引用的垃圾对象清理掉。
-
永久代会不会进行垃圾回收?
在以下几种情况下, 方法区(永久代)里的 类会被回收:
(1)该类的所有实例对象都已经从Java堆内存里被回收;
(2)加载这个类的ClassLoader已经被回收;
(3)对该类的Class对象没有任何引用; -
栈会进行垃圾回收吗?
JVM里垃圾回收针对的是新生代,老年代,还有方法区(永久代),不会针对方法的栈帧。方法一旦执行完毕,栈帧出栈,里面的局部变量直接就从内存里清理掉了。