对象布局
对象头
Mark Word
32bit 4B
64bit 8B
类型指针 Klass pointer
对象所属类的元信息的实例指针
instanceKlass
指针压缩
开启后 4B
关闭 8B
数组长度
如果这个对象不是数组 占 0B
如果这个对象是数组 占4B 表示这个对象数组的元素个数
实例数据
类的非静态属性,生成对象就是实例数据。
对象属性
boolean 2B
byte 1B
char 2B
int 4B
float 4B
double 8B
引用类型:4B(指针压缩) 8B(不压缩)
long 8B
对齐填充
8B字节对齐,java中所有的对象都是8B字节对齐。
如果一个对象占3个字节,JVM会补2个字节凑成32B达到8字节对齐。
为什么要做填充?
1. 效率提高
计算类大小
指针压缩
开启后指针压缩
16B = 8B(markword)+ 4B(klass point) + 0B + 0B = 12
需要补到16
关闭指针压缩
16B = 8 + 8 + 0 + 0
数组对象
开启指针压缩
数组对象在关闭指针压缩的情况下,会出现两端填充。
不止这一种情况。
一个OOP能标识最大堆空间
32bit内存最大 4G
一个OOP,存储的时候是3B,32bit
使用的时候胃部补了3个0, 35bit
OOP32G瓶颈
32G不够用了,需要扩容怎么办?
解决方法:8字节对齐 改成16字节对齐。
8 自己对齐,内存地址会补3个0.16字节对齐会补4个0
32G*2 = 64G
改源码。
JDK为什么没用16字节对齐
1. 没必要
32G已经极限了。GC耗费CPU资源。太大,暂停时间太长。
2. 非空间
总结
- 对象的两种内存结构 kclass,oop
- 计算三种类型的对象大小。
- 指针压缩
调优
- 项目上线前的预估调优。
- 项目上线初期,基于日志做一些基础调优。
- 发生oom,频繁full gc,做测地的调优
- 调优的点
- jvm内存模型的调优。
- 热点代码缓冲区的调优。
案例
- 亿级流量项目的调优
一个UV会访问20个左右的PV
500W用户。
下单转换率 10% = 50W
40%订单在前两小时四完成。
每分钟1200笔订单。
周边流量都加起来,大概
没妙产生200M对象
总共2700M
每个操作要3秒 200 * 3 = 600
每秒钟 600M对象进入Eden区
14秒发生一次young gc
600M对象还存活,无法被回收
触发空间担保。
老年代6400M
多长时间触发一次fullgc
9 * 14 = 126秒一次full gc
本质:
有对象在young gc时未被清理干净。
触发空间担保,动态年龄判断,15次
进入了老年代。
- 解决之道:
对象尽量在 young gc阶段回收掉。
堆最小是物理内存的64份之一,最大是物理内存的4分之一。
oop
java对象在JVM中的存在形式
opp-klass模型
两种对象内存结构
条虫
计算三种类型的对象
开启指针压缩
关闭指针压缩
指针压缩
实现原理
32G瓶颈
如何扩展
JDK源码,OS源码
何为JVM调优
- 预估调优
- 小规模调优
- OOM,full gc频繁
调什么? - 方法区
- 虚拟机栈
- 堆区
- 热点代码缓冲区
亿级流量预估调试实战
GC日志
减少fullgc stw时间太长。