前言:在java虚拟机的自动内存管理机制下,我们并不需要去关心内存分配问题,这极大的方便了程序员的代码开发,但是一旦系统出现内存溢出等问题,出于对虚拟机的不了解,排查问题将异常艰难。
一、运行数据区:
Java虚拟机在执行Java程序的过程中会把它所管理的内存区域划分为若干个不同的数据区域
1.1 程序计数器(线程私有)
程序计数器是一块较小的内存空间,线程私有,可以看作是当前线程所执行的字节码文件的行号指示器;
字节码解释器就是通过改变这个计数器的值来选取下一条需要执行的字节码命令,分支、循环、跳转、线程恢复等基础功能都需要依赖计数器来实现;
Java虚拟机的多线程是通过线程轮流切换并分配处理器时间的方式实现的,在任何一个确定的时刻,一个处理器只会执行一条线程中的指令,每条线程都需要一个独立的程序计数器,各个线程之间的计数器互不影响;
1.2 Java虚拟机栈(线程私有)
虚拟机栈描述的是方法的内存模型:每个方法被执行的同时都会创建一个栈帧用于储存局部变量表、操作栈、动态链接、方法出口等信息;
局部变量表存放了编译期可知的各种基本数据类型,其所需的内存空间在编译器完成分配,在方法运行期间不会改变局部变量表的大小;
1.3 本地方法栈(线程私有)
本地方法栈为虚拟机使用到的Native方法服务;
1.4 Java堆(线程共享)
Java堆存放的是对象实例,是垃圾收集器管理的主要区域;Java堆可以处于物理上的不连续,只要逻辑上是连续的就行
对象访问主流的两种方式:
(1)句柄访问:Java堆中将划分出一块内存区域作为句柄池,句柄池中包含了对象实例数据和类型数据各自的具体地址信息
(2)直接指针: 引用直接储存的就是对象地址
1.5 方法区(线程共享)
方法区用于储存已被虚拟机加载类信息、常量、静态变量、即时编译器编译后的代码等数据
运行时常量池:
Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有运行时常量池,用于存放编译器生成的各种字面量和符号引用,这部分内容将在类加载后存放到运行时常量池中。