JVM入门(四)——Java运行时内存状态变化

506 阅读3分钟

前面JAVA内存结构篇文件从静态的角度介绍了Java的内存结构,下面从示例程序运行的角度再来分析一下程序在java程序在运行时,内存是如何变化。下面首先看一段示例代码:

public class App {

    public static UtilTool utilTool = new UtilTool();
    public static void main(String[] args) {
        DataReader d;
        while (true){
            d = new DataReader();
            d.read();
        }
    }
}

class DataReader {

    public void read(){}
}

class UtilTool {
}

当执行java命令运行上面的程序的时候,jvm是首先加载包含main方法的App.class文件,App类信息被加载到了Jvm的方法区(元数据区),包括静态变量utilTool,utilTool的类型是UtilTool,因此需要再加载UtilTool.class到jvm方法区中,此时内存状态如下图所示:

jvm
根据上面的图中可知,当程序在执行main方法执行,已经把两个类都加载到了方法区,并且在堆中创建了一个UtilTool对象。

jvm把堆空间分为了年轻代和老年代。年轻代一般存放新创建的对象,老年的存放在年轻代存货时间比较长的对象,或者是年轻代无足够空间时,创建的新对象。

然后jvm在JVM中的栈中创建执行main方法到的main线程,然后是执行while循环语句,循环语句中又会创建DataReader对象,因此jvm需要加载DataReader.class文件,然后再在堆中创建一个DataReader对象,此时jvm的内存状态如下图所示:

上面图中所示的是,当main方法第一执行完while中DataReader d = new DataReader();之后的状态图。 接着是调用d.read()方法,此时jvm会在main线程中再创建一个新的栈帧执行d.read()放法,此时状态入下图:

如图所示,main线程中又新增了一个栈帧去执行d.read()方法。当d.read()执行完成之后,d.read()所在的栈帧就会出栈,恢复到了上一个图的样子。while每次循环一次,JVM的堆中就会新创建一个DataReader对象,而之前创建的DataReader对象由于程序中已经没有被其他变量所引用,变成垃圾数据,但是它们会仍然存在于年轻代中,如图所示:

当while循环执行到一定次数之后,年轻代的内存空间已经耗尽,此时当再创建一个DataReader对象时,发现年轻代内存不足,那么此时jvm回启动垃圾回收线程,去清理年轻代中的这些没有用的垃圾对象。垃圾清理之后的java堆中,只保留了一个新创建的DataReader对象状态如下图所示:

随着程序不断的执行,年轻代会再一次被耗尽,然后接着又是JVM启动垃圾回收线程,这样执行多次后,由于年轻代中的UtilTool对象一直被utilTool所引用,没有成为垃圾对象,而经历过多次垃圾回收仍然存活,那么UtilTool对象会从年轻代转移到老年代中。此时java程序的内存状态如图所示

经过上面的分析,大体给大家提供了一个完整的java程序运行时,java内存状态的介绍。感谢大家,谢谢