Java内存区域-读书笔记《深刻理解java虚拟机》
运行时数据区域
程序计数器
- 能够看做是当前线程所执行的字节码的行号指示器
- 线程私有,每条线程都有独立的程序计数器
- 惟一没有OOM状况区域(java虚拟机规范)
java虚拟机栈
- 线程私有
- 描述的是Java方法执行的内存模型
- 每一个方法执行时建立栈帧,用于存局部变量表、操做数栈、动态连接、方法出口等
- 局部变量表在编译时完成分配
- 两种异常
- StackOverflowError:栈深度超过规定
- OutOfMemoryError
本地方法栈
java堆
- 全部线程共享
- 也称:GC堆
- 分为:
- 逻辑上连续,物理上能够不连续的内存空间
- -Xmx、-Xms控制
- 有OOM
方法区
- 全部线程共享
- 习惯称为:永久代,喜欢用永久代来实现方法区而已
- 用于存储:
- 类信息
- 常量
- 静态变量
- 即时编译器编译后的代码
- 等等
- 有OOM
运行时常量池
- 方法区的一部分
- 用于存放编译期生成的各类字面量和符号引用
- 不必定只有编译期才能产生,运行时也可能,例:String.intern()方法
- 有OOM
直接内存
- DirectMemory
- 不是虚拟机运行时数据区一部分
- 也不是java虚拟机规范中定义的区域
- 有OOM
- 不受java堆大小限制
对象建立
给对象分配内存
- 指针碰撞:java堆中内存是绝对规整(已分配与空闲分别在两边)
- 空闲列表:不规整,必须维护一个列表,记录哪些内存可用
- 并发状况
- 分配时同步
- 每一个线程预先分配一块内存(TLAB)
- 分配完成后,内存空间初始化为零值,若是是TLAB,可提早置TLAB时进行
- 而后对对象进行必要的设置,如对象是哪一个类的实例等,存放在对象头中
对象的内存布局
- 对象头(Header)
- 第一部分存储对象自身的运行时数据
- 哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等
- 这部分数据长度在32位和62位(未开启压缩指针)中分别是32bit和64bit
- 官方称为:Mark Word
- 非固定的数据结构
- 另一部分是类型指针
- 指向它的类元数据的指针,经过这个肯定是哪一个类的实例
- 并非全部虚拟机实现都必须在对象数据上保留类型指针
- 若是是数组,对象头中还必须有一块用于记录数组长度的数据
- 实例数据
- 各类类型的字段内容
- 父类中定义的变量出如今子类以前
- 存储顺序受虚拟机分配策略参数(FieldsAllocationStyle)和在源码中定义的顺序影响
- HotSpot虚拟机默认分配策略:
- longs/doubles、ints、shorts/chars、bytes/booleans、oops
- 相同宽度字段老是分配到一块儿
- 对齐填充
- 不是必然存在的
- 也没有特别含义
- 占位符做用
- 使对象大小必须为8字节整数倍
对象访问定位
- 句柄访问
- java堆中分一块内存做为句柄池
- 对象移动时,只需改变句柄中实例数据指针
- 直接指针访问
- 堆对象中必须考虑如何放访问类型数据相关信息
- HotSpot使用
- 速度快
欢迎关注本站公众号,获取更多信息