对象在堆内存中的结构 ? Object o = new Object();这样一行代码 会在内存占用多大空间?

    java -XX:+PrintCommandLineFlags 打印可以看出

-XX:InitialHeapSize=29844928 -XX:MaxHeapSize=477518848 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC

        默认是开启的对象指针压缩和 类指针压缩,用来提高内存的利用率,变量槽 长度 在没开启对象指针压缩 时, Object o = new Object() 变量o 占用一个变量槽。

         64位操作系统,默认是开启对象指针要锁 compressedOops 对象的实例 对象头 mark word 占用 8个字节,class 类型指针占用4字节 填充数据占用 4 字节 16 字节;   

     Object o = new Object();   jvm 对象的起始地址 必须是 8字节的整数倍

          开启压缩: mark word[8 字节] + classPointer[4字节] + 填充数据 [4字节]   = 16 字节

          关闭压缩:mark word[8 字节] + classPointer[8字节]                                  =  16 字节

     o 变量 占用一个变量槽 +UseCompressedOops 占用 4字节,

          -UseCompressedOops 占用 8 字节

          UseCompressedClassPointers requires UseCompressedOops 所以至少 占用 20 字节

不管是否开启类型指针压缩 对象实例都占用 16 字节【jvm 规范规定对象的起始地址必须是8字节的整数倍】,关键就在于是否开启了 对象指针压缩 ,

开启了类型指针压缩,默认就开启了 对象指针压缩,类型指针压缩前置条件就是开启对象指针压缩

  -XX:+UseCompressedClassPointers 则必须 -XX:+UseCompressedOops

         

    说明:局部变量表(Local Variables Table)是一组变量值的存储空间,用于存放方法参数和方法内部定义 的局部变量。在Java程序被编译为Class文件时,就在方法的Code属性的max_locals数据项中确定了该方 法所需分配的局部变量表的最大容量。          局部变量表的容量以变量槽(Variable Slot)为最小单位,《Java虚拟机规范》中并没有明确指出 一个变量槽应占用的内存空间大小,只是很有导向性地说到每个变量槽都应该能存放一个boolean、 byte、char、short、int、float、reference或returnAddress类型的数据,这8种数据类型,都可以使用32位 或更小的物理内存来存储,但这种描述与明确指出“每个变量槽应占用32位长度的内存空间”是有本质 差别的,它允许变量槽的长度可以随着处理器、操作系统或虚拟机实现的不同而发生变化,保证了即 使在64位虚拟机中使用了64位的物理内存空间去实现一个变量槽,虚拟机仍要使用对齐和补白的手段 让变量槽在外观上看起来与32位虚拟机中的一致。对于64位的数据类型,Java虚拟机会以高位对齐的方式为其分配两个连续的变量槽空间。Java语言 中明确的64位的数据类型只有long和double两种。这里把long和double数据类型分割存储的做法与“long 和double的非原子性协定”中允许把一次long和double数据类型读写分割为两次32位读写的做法有些类似

     mark word 对象头 {哈希码,偏向线程id,偏向时间戳,分代年龄[4bit位],锁状态,锁标志位}

     类型指针 [标识 实例对象是属于哪个类型的实例]

     字段填充 [jvm 中要求对象的起始地址是 8字节的整数倍]

     数组长度[数组]

          开启压缩: mark word[8 字节] + classPointer[4字节] + 填充数据 [4字节]   = 16 字节

          关闭压缩:mark word[8 字节] + classPointer[8字节]                                  =  16 字节

 

---------------------------------- 更新-----------------------------------

分配内存:(jvm规范中对象的大小必须是8字节的整数倍)
对象在堆中的结构:
(1)对象头
     mark word [ hash码,GC分代年龄,锁状态,锁标志位,偏向标识,偏向时间戳 ] / 类型指针 / [数组长度]
(2)对齐填充
    Object o = new Object(); 在堆中的大小 16 byte [开启指针压缩]
    对象头 mark word 占用 8个字节,class 类型指针占用4字节 填充数据占用 4 字节 16 字节;
     -XX:+UseCompressedClassPointers -XX:+UseCompressedOops

                          对象头(12 / 16)                 对齐填充(4 / 0 )           变量(o)一个变量槽 (4 / 8)
     开启压缩: mark word[8 字节] + classPointer[4字节] + 填充数据 [4字节]   = 16 字节        +    4字节
     关闭压缩: mark word[8 字节] + classPointer[8字节]                    = 16 字节        +     8字节

     o 变量 占用一个变量槽 +UseCompressedOops 占用 4字节,
     -UseCompressedOops 占用 8 字节
     UseCompressedClassPointers requires UseCompressedOops 所以至少 占用 20 字节

 分配内存的策略:
(1)指针碰撞
    a. 并发冲突的解决:CAS + 重试机制
(2)空闲列表
    b. 本地线程缓冲 Thread local allocate buffer TLAB技术

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值