简述一下jvm(java)内存区域

jvm将内存区域(运行时的数据区)分为五个部分:元空间、堆、虚拟机栈、本地方法栈和程序计数器。

程序计数器:是当前线程在执行的字节码的行号指示器,是线程私有的,每个线程都有一个程序计数器,线程之间的程序计数器是相互独立互不干扰的。这个程序计数器这个区域是java虚拟机规范中唯一没有OOM(OutOfMemoryError)情况的区域。

虚拟机栈:也是线程私有的,生命周期和线程相同。虚拟机栈描述的就是java方法执行的内存模型,每个方法在执行的时候都会创建一个栈帧存放局部变量表、操作数栈、动态链接、方法返回地址信息,每个方法的调用过程就是栈帧在虚拟机栈中入栈到出栈的过程。(栈帧:用来存放数据和部分过程结果的数据结构;栈帧的位置:从内存——>运行时数据区——>虚拟机栈——>到这就是栈帧;栈帧大小从编译时期就确定了,不受运行时的影响。)虚拟机栈顶的栈帧叫做当前栈帧,当前栈帧对应的方法叫做当前方法,所有的执行都是围绕当前方法来执行的。虚拟机栈可能出现的两种异常类型:*Error:当前线程申请的栈空间深度大于虚拟机所允许的深度。OutOfMemoryError:当前虚拟机栈无法申请到足够的内存。局部变量表:一般说的栈就是局部变量表,存放着方法的参数、局部变量、返回值类型和返回值地址。

本地方法栈:功能和虚拟机栈相似,但不同的是虚拟机栈执行的是java方法(字节码文件),而本地方法栈执行的是native本地方法,底层调用的C/C++文件。

堆:堆是线程共享的一块区域,是java虚拟机最大的一块内存区域,java堆用来存放对象实例(大多数情况是这样,但现在有了逃逸分析技术,也可以将对象实例分配到栈上)。同时堆也是垃圾回收的主要区域,也可以叫GC堆,现在垃圾回收主要采用分代回收,有年轻代和老年代。根据虚拟机的规范,堆可以是物理上不连续的内存空间,只要逻辑上连续即可。

方法区:和堆一样,是线程共享的区域。用于存储已经被虚拟机加载的类的类信息(类的名称、类的方法字段信息)、常量、静态变量、编译后的代码。Class文件中除了有类的字段、方法接口等信息之外,还有常量池(用来存储编译期间生成的字面量和符号引用)。方法区中还有一非常重要的部分叫运行时常量池,class文件中的常量池在被类加载后,放入运行时常量池。运行时常量池相对于常量池,具有动态性。

简述一下jvm(java)内存区域