JVM的内存区域可分为两种,一种是线程独立的,内存只能被相应的线程读取,一种是线程共享的,各个线程都可以访问。
线程独立的内存有
- 程序计数器:指向现在正在执行的机器码的行号
- 虚拟机栈:以帧栈作为基本数据结构存放Java方法,
- 本地方法栈:存放Native方法,所谓Native方法是指实现自由,不一定使用java编写。
线程共享的内存有:
- 堆:存放类的实例,数组和GC
- 方法区:存放类的各种信息,常量池(1.7之后移入堆)
对象的创建过程
- 运行时常量池定位类的符号应用
- 检测类有无被初解析
- 为类的实例分配内存
- 空闲列表法:从堆的空闲区域选取能满足需求的块,适用于不规整的堆
- 指针碰撞法:移动指针表示该区域已被使用,仅限于规整的堆
- 将分配内存清零
- 一些其他的必要设置
对象在堆中的数据结构
- 对象头: 运行时数据 Mark Word(锁信息在其中),类型指针,长度(数组专有)
- 实例数据:真正有效的实例数据,由单位从大至小排序,比如从long到byte
- 对齐填充:占位符
如何定位对象
- 句柄法:由句柄指向实例数据和对象类型数据,两者如之前所说,分别位于堆和方法区。优点是句柄位置是稳定的。
- 直接指针:由实例数据指向对象类型数据。优点是只用一次定位,比句柄法少一次,更节省时间成本。