一、JVM内存模型
运行时数据区

程序计数器
线程私有的一块内存区域,存放的是下一条要执行的指令地址
1. 调用 native 方法时,该值为空
2. 不会出现 OutOfMemory,当线程过多时,堆内存会首先溢出
3. 随线程的消亡而消亡
虚拟机栈
java方法区的内存模型,线程私有
1. 一个方法对应一个栈帧
2. 一个线程可能会包含多个栈帧
本地方法栈
与虚拟机栈类似,为 native 方法服务
堆
存放对象和数组
1. 所有线程共享
2. GC的主要场所
方法区
存放虚拟机加载的类信息、常量、静态变量、编译后的代码等数据
1. 所有线程共享
2. 常量池
非虚拟机内存(堆外内存)
由操作系统来分配,虚拟机来引用
1. 可以由 -XX:MaxDirectMemorySize 指定
2. 受本机总内存影响
3. 性能提升,不用通过系统复制到java堆上
二、对象的内存布局

对象头
运行时数据

哈希码、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()
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。