• 7.jvm对象内存布局


    概述

    jvm对象内存布局详解。

    相关文章在此总结如下:

    文章地址
    jvm基本知识地址
    jvm类加载系统地址
    双亲委派模型与打破双亲委派地址
    运行时数据区地址
    运行时数据区-字符串常量池、程序计数器、直接内存地址
    jvm中对象创建流程与内存分配地址

    对象里的三个区

    对象里有啥?
    在这里插入图片描述

    对象头

    对象头:8字节,如果是数组12字节(记录数组长度,占4字节)

    • 标记字段:存储对象运行时自身数据

      • 默认:对象Hashcode、GC分代年龄、锁状态
      • 存储数据结构并不是固定的
    • 类型指针:对象指向类元数据的指针

      • 开启指针压缩占4字节、不开启8字节 (jdk1.6之后默认是开启的)
    • 数组长度:如果是数组,则记录数组长度,占4个字节

    • 对其填充:保证数组(针对的是数组)的大小永远是8字节的整数倍

                          32位Markword是可变的数据结构,对象头总大小固定8字节
      
      • 1

    在这里插入图片描述

    Markword 占4个字节,共32位。

    					64位Markword是可变的数据结构,对象头总大小固定12字节
    
    • 1

    在这里插入图片描述

    在这里插入图片描述

    验证

    打印空对象的内存而已信息

    代码
    <dependency>
        <groupId>org.openjdk.jolgroupId>
        <artifactId>jol-coreartifactId>
        <version>0.9version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    执行代码

    package com.fun.info;
    
    import org.openjdk.jol.info.ClassLayout;
    
    public class ObjLock {
        public static void main(String[] args) {
            Object o = new Object();
            System.out.println("new Object:"+ ClassLayout.parseInstance(o).toPrintable());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    控制台输出

    在这里插入图片描述

    分析
    • 首先对象头是包含 Markword类型指针 这两部分信息
    • 开启指针压缩的情况下,存放 Class 指针的空间大小是4字节,Markword是8字节,对象头为12个字节
    • 新建 Object 对象,会在内存占用16个字节,其中 Header 占12个(Markword 占8个 + ClassPoint 占 4个),没有实例数据,补充对齐 4 个字节

    验证2

    基本数据类型和包装类的内存占用情况

    数据类型内存占用 (byte)
    boolean1
    byte1
    short1
    char2
    int4
    float4
    long8
    double8
    Boolean4
    Byte4
    Short4
    Character4
    Integer4
    Float4
    Long4
    Double4
    代码
    package com.fun.info;
    
    import org.openjdk.jol.info.ClassLayout;
    
    public class ObjLock2 {
        public static void main(String[] args) {
            Student o = new Student();
            System.out.println("new Object:"+ ClassLayout.parseInstance(o).toPrintable());
            o.setAge(10);
            o.setFlag(true);
            o.setName("abc");
            System.out.println("赋值 new Object:"+ ClassLayout.parseInstance(o).toPrintable());
    
        }
    
        static class Student{
            private boolean flag;
            private int age;
            private String name;
    
            public boolean isFlag() {
                return flag;
            }
    
            public void setFlag(boolean flag) {
                this.flag = flag;
            }
            
            public void setAge(int age) {
                this.age = age;
            }
    
            public void setName(String name) {
                this.name = name;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    控制台输出

    在这里插入图片描述
    在这里插入图片描述

    总结: 对象从创建,对象的大小就已确定了。

    实例数据

    对象内部的成员变量

    对其填充

    8字节对象,保证对象大小是8字节的整数倍。

    访问对象

    如何访问对象?

    在这里插入图片描述
    在这里插入图片描述

    两种方式如上两图:

    • 1.句柄
    • 2.直接指针

    结束

    至此,jvm对象内存布局就说得明明白白了,如有疑问,欢迎评论区留言。

  • 相关阅读:
    基于C++和QT实现的房贷计算器设计
    2021年InfoWorld 精选最佳开源软件
    VirtualBox安装Centos
    .Net CLR GC 动态加载短暂堆阈值的计算及阈值超量的计算
    Linux多线程服务端编程:使用muduo C++网络库 学习笔记 第四章 C++多线程系统编程精要
    动环监控设备维护与故障处理,动环监控系统调试
    电脑文件误删除如何恢复?
    MySQL·SQL优化
    手撕前端面试题(Javascript~事件委托、数组去重、合法的URL、快速排序、js中哪些操作会造成内存泄漏......
    [NLP] Llama2模型运行在Mac机器
  • 原文地址:https://blog.csdn.net/2301_79691134/article/details/134373480