1.简述Java虚拟机(JVM)内存区域划分及其作用
1).程序计数器(线程私有)
记录当前线程的字节码指令执行到哪里了,每个线程有自己的计数器,
所以,在内存中有自己独立的区域用来存储计数器相关的数据。
2).虚拟机栈(线程私有)
和程序计数器一样,也是每个线程有自己的虚拟机栈,由一个个的栈帧组成,每个栈帧对应一个方法的调用,
栈帧包含局部变量表、操作数栈、动态链接、方法返回地址
局部变量表: 局部变量
操作数栈:中间结果和运算操作数
动态链接:是一种机制,它确保了当通过基类引用或接口引用调用方法时,JVM能够根据对象的实际类型找到并执行正确的子类或实现类中的方法版本。
方法返回地址:记录了方法执行的代码位置,方便方法处理完后继续正常向下执行,有点类似程序计数器,但是这个是针对方法的位置记录,程序计数器是细致字节码的记录
3).本地方法栈(线程私有)
存储了本地方法调用的状态,包括局部变量、操作数栈等,类似于Java虚拟机栈中存储Java方法的信息。
但与Java虚拟机栈不同的是,它服务于的是非Java代码,即那些用C、C++等本地语言实现的方法。
4).堆(线程共享)
存储着局部对象和引用类型的静态资源(引用存储在元空间,但指向是堆)等资源,是垃圾回收机制主要清理的区域,内部分为年轻代,老年代
5).方法区/元空间
方法区是一个概念,元空间是实现,用来存储类的元数据,类的结构信息(如类的字段、方法),方法代码、常量池(指向存储在堆)
栈内存与线程的关系
每个线程都有自己的栈内存,用于存储局部变量、操作数栈、方法调用信息等。由于栈是线程私有的,所以一个线程的栈内存对其他线程是不可见的。
元空间与对象引用
元空间存储了类的元数据信息,包括类的结构信息等。静态变量虽然存储在元空间(准确说是静态变量的定义和类型信息存储在元空间,而静态变量的值如果是基本类型则直接存储在堆中,如果是对象引用则存储引用在元空间),但静态变量的值(不论是基本类型还是对象引用)并不直接指向栈内存中的数据。
对象引用与栈内存
当一个方法内部声明了一个对象,并将其赋值给一个局部变量时,这个对象实例存储在堆中,而局部变量(对象引用)存储在调用该方法的线程栈上。如果静态变量引用了一个对象,这个引用实际上存储在元空间(如果是对象引用的话),它指向的是堆中的对象实例,而不是直接指向另一个线程的栈内存中的局部变量。