主要记录学习《深入理解java 虚拟机笔记》图书过程中个人比较关注内容
[toc]
是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。每条线程都有一个独立程序计数器,相互独立存储! 如果执行java方法,则计数器指向执行的字节码地址;如果是native的方法,则为空。 该区域是java虚拟机规范中唯一一个没有规定任何OOM的区域
- java 方法执行的内存模型:每个方法执行的同时会创建一个栈帧(Stack Frame)用于存储局部变量表,操作数栈,动态链接,方法出口等信息。每个方法从调用到直至完成,对应这一个栈帧在虚拟机栈中的入栈到出栈过程。
- 局部变量存放三种类型数据:
- 基本类型数据
- 对象引用
- returnAddress类型(指向一条字节码指令的地址,具体咱不明白)
- 线程私有且生命周期和线程相同
- java虚拟机规范规定该区域存在两种异常: 1. stackOverflowError 2. OOM
- 存放对象实例。
- 存在OOM方法异常
- 线程共享
- 虚拟机调用Native方法一个过程,与虚拟机方栈比较相似
- 主要用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码数据等。
- 线程共享
- 运行时常量池是方法区一部分,用于存储编译器生成的字面量和符号引用,这部分内容将在类加载后静茹方法区的运行时常量池中存放。 具有动态性,可以在运行时放入常量池常量
- 存在OOM异常
- 直接内存(Direct Memory)并不是虚拟机运行时数据的一部分,也不是java虚拟机规范中定义的内存区域,但是使用频繁
- NIO引入一种基于通道与缓冲区的I/O方式。可以直接Native函数调用堆外内存。通过存储在堆上DirectByteBuffer对象作为内存引用进行操作,避免java堆和native堆来回复制数据,提高性能
一个java对象创建过程:
- new 指令触发时,首先检查参数是否在常量池中定位到类引用,并且检查该类是否被加载,解析,初始化过。
- 分配内存。
- 内存空间初始化为零
- 对对象进行必要设置(类的元数据信息,对象哈希码等存放对象头)
- 实现init方法初始化对象
HotSpot虚拟机中,对象在内部存储布局为3区域:对象头(Header)、实际数据和对齐填充
- **对象头(Mark word)**主要包括两个部分 1. 存储对象本身的运行数据 2. 类型指针,即对象指向它的类元数据,虚拟机通过这个指针来确定这个对象是哪个类实例
- 实例数据 继承父类,子类中定义的全部存储。
- 对齐填充 由于HotSpot vm 自动内存管理系统必须要求对象起始地址必须8字节的整倍数,所以起到对为满八位倍数的占位符作用
reference 类型只存储一个对象引用地址,对象访问定位就是具体获取对象具体位置方法。目前主流两种方法:句柄,直接指针