第二部分:自动内存管理机制。包括2-5章
第2章 Java内存区域与内存溢出异常
2.1 概述
– 虚拟机自动内存管理机制
– Java程序员把内存控制的权力交给了Java虚拟机
本章从概念上介绍Java虚拟机内存的各个区域
2.2 运行时数据区域
Java虚拟机运行时数据区:

1、程序计数器
行号指示器;线程私有;没有规定任何OutOfMemoryError情况的区域
2、Java虚拟机栈
线程私有;
描述的是Java方法执行的内存模型:创建一个栈帧(Stack Frame,用于存储局部变量表、操作数栈、动态链接、方法出口 等信息)。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出 栈的过程;
虚拟机栈中局部变量表存放了
各种基本数据类型
对象引用
returnAddress类型(指向了一条字节码指令的地址)
局部变量表所需的内存空间在编译期间完成分配,局部变量空间是完全确定的,不会改变。
该区域有2种异常:
- StackOverflowError:线程请求的栈深度大于虚 拟机所允许的深度
- OutOfMemoryError:虚拟机栈扩展时无法申请到足够的内存
3、本地方法栈
与虚拟机栈所发挥的作用是非常相似;
本地方法栈则为虚 拟机使用到的Native方法服务;
也会抛出StackOverflowError和OutOfMemoryError异常;
4、Java堆
线程共享,在虚拟机启动时创建;
目的:存放对象实例;
也被称做“GC堆”(Garbage Collected Heap),是垃圾收集器管理的主要区域;
Java堆中可能划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer,TLAB);
5、方法区
线程共享;
用于:存储已被虚 拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
别名叫做Non-Heap(非堆);
当方法区无法满足内存分配需求时,将抛出 OutOfMemoryError异常
运行时常量池: (Runtime Constant Pool)是方法区的一部分
用于 : Class文件常量池存放编译期生成的各种 字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常 量池中存放;
运行时常量池相对于Class文件常量池的另外一个重要特征是具备动态性;
受到方法区内存的限制,当常量池无法再申 请到内存时会抛出OutOfMemoryError异常;
6、直接内存
并不是虚拟机运行时数据区的一部分;
使用Native函数库直接分配堆外内存(NIO(New Input/Output)类);
动态扩展时出现OutOfMemoryError异常(经常忽略 直接内存,使得各个内存区域总和大于物理内存限制);
2.3 HotSpot虚拟机对象探秘
虚拟机中对象的创建过程(new指令):
1、确保常量池中存放的是已解释的类
2、确保对象所属类型已经经过初始化阶段(否则必须先执行相应的类加载过程)
3、为新对象分配内存
如何划分可用空间?
–内存规整:指针碰撞
–内存不规整:空闲列表
如何保证并发下的线程安全?
–同步处理:CAS+失败重试保证原子性
–本地线程分配缓冲(Thread Local Allocation Buffer,TLAB):按照线程划分在不同的空间
4、为对象初始化零值
5、设置对象头信息
6、将对象引用入栈
7、执行new指令之后(所有的字段都还为零)会接着 执行<init>方法(把对象按照程序员的意愿进行初始化)



