一、JVM内存模型

运行时数据区

image.png

程序计数器
线程私有的一块内存区域,存放的是下一条要执行的指令地址
1. 调用 native 方法时,该值为空
2. 不会出现 OutOfMemory,当线程过多时,堆内存会首先溢出
3. 随线程的消亡而消亡
虚拟机栈
java方法区的内存模型,线程私有
1. 一个方法对应一个栈帧
2. 一个线程可能会包含多个栈帧
本地方法栈
与虚拟机栈类似,为 native 方法服务
存放对象和数组
1. 所有线程共享
2. GC的主要场所
方法区
存放虚拟机加载的类信息、常量、静态变量、编译后的代码等数据
1. 所有线程共享
2. 常量池

非虚拟机内存(堆外内存)

由操作系统来分配,虚拟机来引用
1. 可以由 -XX:MaxDirectMemorySize 指定
2. 受本机总内存影响
3. 性能提升,不用通过系统复制到java堆上

二、对象的内存布局

image.png

对象头
运行时数据

image.png

哈希码、GC分代年龄、锁状态标志等
8字节(32位4字节)
类型指针
类元数据的指针
reference类型占用8字节(32位虚拟机4字节)
数组长度的数据(数组对象时才有)
8字节(32位虚拟机4字节)~~~~
实例数据
具体的对象内的数据
对齐填充
对象的起始地址必须是8的整数倍,可能需要进行补充对齐
(对象头 + 实例数据 + padding) % 8 = 0且0 <= padding < 8

三、对象的访问

句柄
对象移动时不用修改 reference ,只用修改句柄池中的实例指针数据
对象实例数据的指针(堆)
对象类型数据的指针(方法区)

直接指针

访问速度快
reference 存放的是堆中对象的内存地址

FAQ

OOM
-Xms、-Xmx修改大小
栈溢出
-Xss栈容量,栈帧越大(方法参数、变量越多),栈深度越小
线程请求的栈深度大于虚拟机允许的最大深度,StackOverflowError
扩展栈时无法申请足够的内存空间,OutOfMemoryError
线程过多
方法区溢出
-XX:PermSize、-XX:MaxPermSize
String.intern()增加常量池的使用容量
CGLib动态生成Class
直接内存溢出
-XX:MaxDirectMemorySize
Unsafe.allocateMemory()

tank
2 声望0 粉丝

致命风华