1.程序计数器
1.1 程序计数器在内存中占用较小的一块内存,主要作用是记录当前线程执行的程序的字节码的地址。
1.2 各个线程的程序计数器是独立存储互不干涉的。
1.3 如果线程执行的是一个Java方法,程序计数器指向虚拟机中该程序字节码的地址;
如果执行的是Native方法,则这个计数器为Undefined。
2.Java虚拟机栈
2.1 虚拟机栈用来描述Java方法执行的内存模型,每个Java方法执行时都会创建一个栈帧,用来存储局部变量、操作栈、动态链接、方法出口等。
每一个方法调用到执行完毕都对应了一个栈帧在虚拟机栈中从入栈到出栈的过程。
2.2 局部变量表存放了编译器可知的基本数据类型、对象引用类型、64位长度的long和double类型会占两个局部变量空间(Slot)
2.3 虚拟机栈也是线程私有的
2.4 虚拟机栈中定义了两种异常情况:StackOverflowError异常、OutOfMemoryError异常;
2.4.1 StackOverflowError 会出现在线程请求的深度大于虚拟机允许的深度时
2.4.2 OutOfMemoryError 会出现在当需要内存扩展时,虚拟机无法申请到足够的内存时
3.本地方法栈
3.1 本地方法栈和虚拟机栈类似,前者是为本地Native方法服务,而后者是为Java方法服务。
3.2 本地方法栈也包括上述两种异常情况
4.Java堆
4.1 Java堆是JVM管理的最大的一块内存区域,也是被所有线层共享的一块区域,在虚拟机启动时创建。
4.2 该区域的唯一作用就是存放对象实例
4.3 该区域也是GC工作的主要区域,所以很多时候也被叫做GC堆。
4.4 Java堆可以存在于物理上不连续的内存中,逻辑上连续即可。
5.方法区
5.1 多个线程共享的内存空间,用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码数据等。
5.2 对于sun的HotSpot虚拟机来说,方法区也被叫做永久带(Permanent Generation)
5.3 异常情况:OutOfMemoryError
6.运行时常量池
6.1 是方法区的一部分,用于存放编译器生成的各种字面量和符号引用
6.1.1 符号引用:就是在字节码文件中以一组符号来表示所引用的目标,比如Student类中引用了Teacher类,
但是实际上Student并不知道Teacher的地址在哪于是可以使用一组符号来表示Teacher的引用。
6.1.2 直接引用:与符号引用对应的就是直接引用了;
直接引用可以是一个直接指向目标的指针(指向Class对象,类变量、类方法的 直接引用可能是指向方法区的指针)
或者是一个相对偏移量(指向实例变量实例方法的直接引用)
或者是间接定位的句柄
6.2 运行时常量池是动态的,不仅是编译器的常量,运行时的常量都可以放在池中,String类的intern()方法便是
6.3 OutOfMemoryError 异常情况
7.直接内存
7.1 直接内存并不是虚拟机运行时内存的一部分,也不是Java定义的内存区域,但是经常被使用,也可能会出现OutOfMemoryError异常情况。
7.2 JDK1.4后引入了NIO(new Input/Output)支持了基于通道和缓冲区的I/O方式,可以直接通过Native函数分配堆外内存,好处是不用再Native堆和Java堆中来回复制数据。