回顾一下,之前已经讲过,Java项目要运行起来,需要经过三步:编译-->加载-->运行。JVM是通过类加载器把类加载到内存中来的,加载的机制是双亲委派制。那JVM的内存结构是怎么样的呢?请看图:
编辑搜图
请点击输入图片描述
总的来说分为两部分,线程共享的区域和线程私有的区域。线程共享:堆和方法区;线程私有:虚拟机栈、本地方法栈和程序计数器。
下面以一小段代码为例,说明下各区域的作用,代码如下:
编辑搜图
请点击输入图片描述
1.元数据区(jdk1.8之前叫方法区)
该区域主要是存放加载到内存中的class对象和常量池。当示例代码执行到19行时,会把User.class加载到内存中来,这个class对象就放在元数据区。
2.堆
堆主要存放的是我们创建的类的实例对象。如实例代码19行,会创建一个user对象,这个对象就是放在堆内存里。
3.虚拟机栈
每个线程都有自己的虚拟机栈,这个区域主要是存放方法内的局部变量等。如19行的user引用就放在虚拟栈里,这个user引用相当于一个指针,指向堆内存中的实例对象。
每个方法都会有创建一个栈帧,压入到虚拟机栈中,每个栈帧存放的就是方法的局部变量,操作数等。如示例代码中执行到main方法会创建一个栈帧,打印时执行到user的toString方法,也会创建一个栈帧,当方法执行完了,栈帧也就出栈消失了。
4.本地方法栈
和虚拟机栈的作用类似,大家看Java类库的代码,会发现有很多是native方法,如public native
int hashCode()。当线程调用这种方法时,用的就是本地方法栈。
5.程序计数器
Java是支持多线程的,各线程要抢CPU时间片,有可能A线程执行了一半,CPU就被线程B抢去了。这个时候A线程就需要记录下程序执行到位置,以便拿到CPU执行权后接着执行。JVM执行的是字节码wej,程序计数器存的就是每个线程字节码执行到的位置。
关注我,一起学!哈哈。