7.jvm对象内存布局

目录

  • 概述
  • 对象里的三个区
    • 对象头
      • 验证
        • 代码
        • 控制台输出
        • 分析
      • 验证2
        • 代码
        • 控制台输出
    • 实例数据
    • 对其填充
  • 访问对象
  • 结束

概述

jvm对象内存布局详解。

相关文章在此总结如下:

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

对象里的三个区

对象里有啥?
7.jvm对象内存布局_第1张图片

对象头

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

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

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

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

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

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

7.jvm对象内存布局_第2张图片

Markword 占4个字节,共32位。

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

7.jvm对象内存布局_第3张图片

7.jvm对象内存布局_第4张图片

验证

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

代码
<dependency>
    <groupId>org.openjdk.jolgroupId>
    <artifactId>jol-coreartifactId>
    <version>0.9version>
dependency>

执行代码

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());
    }
}
控制台输出

7.jvm对象内存布局_第5张图片

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

验证2

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

数据类型 内存占用 (byte)
boolean 1
byte 1
short 1
char 2
int 4
float 4
long 8
double 8
Boolean 4
Byte 4
Short 4
Character 4
Integer 4
Float 4
Long 4
Double 4
代码
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;
        }
    }
}
控制台输出

7.jvm对象内存布局_第6张图片
7.jvm对象内存布局_第7张图片

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

实例数据

对象内部的成员变量

对其填充

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

访问对象

如何访问对象?

7.jvm对象内存布局_第8张图片
7.jvm对象内存布局_第9张图片

两种方式如上两图:

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

结束

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

你可能感兴趣的:(jvm,jvm,对象内存布局)