由于之前只是上过一门C语言编程课应付考试,以及通过网课了解一些C++语法,程序执行时的具体内存空间分配对于我来说就是一个黑箱。所以在开始学习Java时,我打算了解一下内存空间的基础概念,不求真正理解JVM,只是想能够大概清楚程序的执行是一个怎样的流程。这篇文章只是记录我一些简单的学习体会。
下面是我根据网络资料和一些个人理解绘制的一张简单的示意图,不仅包含内存空间的类型,还有类加载的流程。
Java程序的旅程
在Java的世界里,一切皆对象,所有的方法也都被封装在类的内部,可以说是一门纯粹的OOP语言。我们编写的所有Java代码也都是抽象成一个又一个的类而存在。像我这样的初学者都知道:Java文件经过javac编译成class文件,class文件再交由虚拟机JVM去执行。
然而虚拟机究竟是如何执行class文件的,就是我这篇文章想要分享的。
由上图可以看到,我将运行时的数据空间分成了三块(实际不止,还有本地方法栈和程序计数器),以及额外添加了一个本地磁盘来说明类加载,虚拟机栈是线程私有的,而堆和方法区都是线程共享的。网上关于数据空间的博文有很多,就不一一细说了。
现在假设我们的主程序代码如下:
public class demo{
public static void main(String args[]){
Student stu = new Student;
Student.method();
}
}
Student类的定义就不写了,只是一个简单的示范而已。主要说一下执行的过程:
-
JVM将main方法加载进虚拟机栈,开始执行main内部代码
-
JVM读取到
new Student()
,于是前往方法区寻找Student相关信息 -
JVM未查找到Student类信息,从磁盘中加载Student.class文件进入内存
加载class文件的过程,详见上图中类加载的五步流程图即可
-
加载完成后,JVM根据Student的class对象在堆内创建相应的Student对象stu,并将stu的符号引用转换为直接引用(赋予堆内地址)
-
JVM继续读取到
stu.method()
(图中误写为Student),根据stu索引到堆内的对象 -
JVM将对象内方法method加载进栈,开始执行method方法内部代码
-
method执行完毕后将直接出栈,随后在main中继续向下执行
也就是说,JVM执行时以class文件为基本单位,遵循“需要什么加载什么”的原则。和上一篇关于反射的文章对比阅读,也就对于Java为什么需要反射机制有了更加深刻的理解。