概述
java虚拟机在执行java程序的时候会把它所管理的内存分为若干个不同的区域,每个区域有不同的功能、以及创建和销毁时间,有些区域随着虚拟机的启动而存在,有些区域随用户线程的启动和结束创建和销毁。
1. 程序计数器:
程序计数器占用的内存比较小,它是当前线程所执行的字节码的行号指示器,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器完成。
该内存空间是线程私有的,多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,同一时间处理器只会处理单个线程的指令,每个线程都需要记录本线程当前执行的字节码指令位置,各个线程之间互不影响,独立存储。
如果线程执行的是java方法,则这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果java虚拟机执行的是Native方法,则计数器的值为空。该内存区域为虚拟机中唯一没有OutOfMemoryError的区域。
2. java虚拟机栈:
特点:线程私有
生命周期:和线程相同,随着线程的创建而产生,线程执行结束而回收
内部结构:以栈帧的形式运行和存储数据,每个方法执行的同时会创建栈帧,用于存储局部变量表(this, 方法参数),操作数栈(java是基于栈的执行引擎,其实说的就是操作数栈,用于执行java字节码指令)、动态连接(代码运行期间将符号引用转换成直接引用)和方法出口(记录返回到方法被调用的位置)等信息。每个方法的调用到执行完成对过程对应的是栈帧在虚拟机中入栈和出栈的过程。
异常: StackOverflowError:线程请求的栈深度大于虚拟机所允许的栈深度
OutOfMemoryError:如果java虚拟机栈在动态扩展到时候无法申请到足够的内存
3. 本地方法栈:
和java虚拟机栈的作用是相似的,只是java虚拟机栈调用的是java方法,本地方法栈则是java虚拟机使用到Native方法服务。
4. java堆
简单介绍: 所有的对象都需要在该内存区域存储。该区域是所有线程共享的,java虚拟机内存管理中最大的一块内存空间。垃圾收集器管理的主要区域,可分为Eden空间、Form Survivor空间、To Suivivor空间。
异常信息: 如果堆中没有足够的内存区域完成对象的内存分配,则会抛出OutOfMemoryError一次。
5. 方法区:
特点: 线程共享
存储信息:
- 类信息:
- 类型全限定名。
- 类型的直接超类的全限定名(除非这个类型是java.lang.Object,它没有超类)。
- 类型是类类型还是接口类型。
- 类型的访问修饰符(public、abstract或final的某个子集)。
- 任何直接超接口的全限定名的有序列表。
- 类型的常量池。
- 字段信息。
- 方法信息。
- 除了常量意外的所有类(静态)变量。
- 一个到类ClassLoader的引用。
- 一个到Class类的引用。
- 常量:final
- 静态变量:类变量,static
- 即时编译器编译后的代码:xxx
- 运行时常量池:存储编译期生成的各种字面量和符号引用