《深入理解Java虚拟机》第二章笔记
目录
1 运行时数据区域
包含五个部分:
线程共享:方法区、堆
线程隔离:虚拟机栈、本地方法栈、程序计数器
1.1 程序计数器
(1)占用内存空间较少,可以被看作当前线程所执行的字节码的行号指示器。
(2)如果线程正在执行Java方法,则程序计数器记录的是字节码指令的地址;如果正在执行Native方法,则计数器值为空
(3)在Java虚拟机规范中唯一一个没有规定任何OutOfMemoryError情况的区域。
1.2 Java虚拟机栈
(1)存储的是一个个栈帧,栈帧中存储的是局部变量表、操作数栈、动态链接、方法出口信息等(每个方法从调用直至执行完成,就对应着一个栈帧在虚拟机栈中的入栈和出栈)。
(2)异常:若线程请求的栈深度大于虚拟机所允许的深度,则抛出StackOverflowError异常;若虚拟机可以动态扩展,且扩展时无法申请到足够的内存,则抛出OutOfMemoryErrory异常。
1.3 本地方法栈
(1)与虚拟机栈作用类似。与Java虚拟机栈区别是:Java虚拟机栈为执行Java方法服务,而本地方法栈为Native方法服务。
(2)与虚拟机栈类似,也会抛出StackOverflowError异常和OutOfMemoryErrory异常。
1.4 Java堆
(1)占用内存空间最大,该区域的唯一目的就是存放对象实例。
(2)若在堆中没有内存进行分配,且无法再扩展,则抛出OutOfMemoryError异常。
1.5 方法区
(1)存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
(2)若方法区中没有内存进行分配,则抛出OutOfMemoryError异常。
1.6 运行时常量池
(1)是方法区的一部分。
(2)Class文件中的常量池存放的是编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入运行时常量池存放。
(3)若没有内存进行分配,则抛出OutOfMemoryError异常。
1.7 对象的内存布局
对象在内存中的布局可分为三部分:对象头、实例数据、对齐补充。
①对象头分为两部分,第一部分存储对象自身的运行时数据(eg:哈希码);第二部分是类型指针,即指向它的类元数据的指针
②实例数据对象真正有用的信息,即程序中定义的各种类型的字段内容。
③对齐补充,非必然存在,仅作占位符作用,满足对象起始地址必须是8字节的要求。
1.8 对象的访问定位
访问方式有两种:句柄和直接指针。
优缺点:使用句柄的优势是稳定的句柄指针,当对象被移动时只会改变句柄中的实例数据指针;使用直接指针的优势是速度更快,它节省了一次指针定位的时间开销。