Java内存模型
a.程序计数器
作用:
取下一条待执行的指令
特点:
线程独立,非共享,不存在OutOfMemoryError
b.虚拟机栈
作用:
生命周期与每个方法(字节码)对应一个栈帧,存储局部变量/操作数/方法出口
方法的调用-执行-返回对应虚拟机栈的入栈和出栈
说明:
局部变量编译期空间分配完成 4类8种中除long double占用两个局部变量空间,其他占一个空间。
异常:
(1)线程请求的栈深度大于虚拟机所允许的深度 StackOverflowError
(2)虚拟机扩展无法申请到足够的内存 OutOfMemoryError
c.本地方法栈
作用:
Native方法服务栈
特点:
与虚拟机栈相似,如:Sun HotSpot虚拟机直接把本地方法栈和虚拟机栈合二为一
d.堆
作用:
存放对象实例/数组
时机:
虚拟机启动时创建
特点:
线程共享 垃圾收集器管理的主要区域
实现:
逻辑连续,可扩展,通过-Xmx -Xms控制
异常:
如果在堆上没有内存完成实例分配,且无法扩展 OutOfMemoryError
e1.方法区
作用:
存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据
特点:
线程共享 Sun HotSpot虚拟机称为“永久代”,可垃圾回收 JDK1.7之后字符串常量池不存放在永久代
异常:
永久代上限 -XX:MaxPermSize 无法满足内存分配需求 OutOfMemoryError
e2.运行时常量池
作用:
方法区一部分 存放编译期生成的各种字面量和符号引用
特点:
String的intern()方法 在运行期间将新的常量放入常量池
异常:
无法申请内存 OutOfMemoryError
f.直接内存
说明:
不属于java虚拟机内存,但由于jdk1.4后NIO的引入 可以使用Native函数直接分配堆外内存
异常:
受系统物理内存影响,无法申请内存 OutOfMemoryError
对象创建
a.两种分配方式
1.指针碰撞:连续(理解为数组)
2.空闲列表:非连续(链表)
说明:
看java堆的内存是否规整
b.两种分配方式解决并发
1.同步
2.本地线程分配缓冲(线程独立分配,不足再扩展,通过-XX:+/-UseTLAB)
对象内存布局
a.对象头
1.第一部分
说明:
存储对象自身的运行时数据(HashCode),GC分代年龄,锁状态标志,线程持有的锁,偏向线程的id,偏向时间戳
大小:
32位虚拟机:32bit 64位虚拟机:64bit
2.第二部分
说明:
指针类型,指向它的类元数据的指针,确定是哪个类的对象
其他:
如果是数组,还需要记录数据长度
b.实例数据
说明:
代码中所定义的字段内容
c.对齐填充
说明:
占位符
原因:
对象起始地址必须是8字节的整数倍,对象的大小必须是8字节的整数倍
因此,当对象实例数据部分没有对齐时,需要通过对齐填充来补全
对象访问定位
a.使用句柄
特点:
二次定位,对象地址变更,栈中reference不变
b.直接访问
特点:
一次定位,速度快,Sun HotSpot虚拟机使用