【JVM深入理解系列3】底层优化

对象布局

对象头
    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. 非空间

总结

  1. 对象的两种内存结构 kclass,oop
  2. 计算三种类型的对象大小。
  3. 指针压缩

调优

  1. 项目上线前的预估调优。
  2. 项目上线初期,基于日志做一些基础调优。
  3. 发生oom,频繁full gc,做测地的调优
  • 调优的点
  1. jvm内存模型的调优。
  2. 热点代码缓冲区的调优。

案例

  • 亿级流量项目的调优

一个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调优

  1. 预估调优
  2. 小规模调优
  3. OOM,full gc频繁
    调什么?
  4. 方法区
  5. 虚拟机栈
  6. 堆区
  7. 热点代码缓冲区

亿级流量预估调试实战

GC日志

减少fullgc stw时间太长。

No Comment Yet