IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> java对象的内存布局 -> 正文阅读

[数据结构与算法]java对象的内存布局

java对象内存布局简介

java对象的内存布局包含对象头、实例数据、对齐填充

对象头

  • markword:对象默认的hash码、分代年龄,锁的状态标识等。
  • class point:指向对象对应的类的元数据内存地址(堆指向方法区)。也就是指向Class的字节码。
  • length :数组对象持有的数组长度,只有数组特有。

markword

用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等等。

markword多长呢,是分虚拟机的。32位jvm的mark的长度是32,,4位jvm的markword的长度是64。具体存储的内容及内容长度如下:

32位jvm的markword存储:
在这里插入图片描述
64位jvm的markword存储:
在这里插入图片描述
上面的两个图片如何解析呢?
无锁状态下64位jvm前25bit没用到,存0;
接下来的31bit存对象的hashCode;
接下来的1bit未用到,存0;
接下来的4bit存分代年龄;
接下来的1bit存是否偏向锁;
接下来的2bit存锁标识位;
这样就知道64位的markword都存了什么东西。其他的锁状态分析与无锁状态类似。

指针

上面的markword存储的是运行时数据,比如这个对象的hashcode、锁的状态、垃圾回收信息等。
而指针中存储的的是指针,指针是干嘛的?指针是指向方法区的,说明这个对象是什么类型的。
64位jvm指针的长度是64bit。
需要注意的是,jdk1.8默认是开启压缩的,压缩完的指针就变成了32bit。可以通过参数-XX:-UseCompressedOops关闭指针压缩。

length

length中存储的是数组长度,64位jvm数组长度占32bit。

实例数据

主要是存放类的数据信息,父类的信息,对象字段属性信息。

如果对象有属性字段,则这里会有数据信息。如果对象无属性字段,则这里就不会有数据。根据字段类型的不同占不同的字节,例如boolean类型占1个字节,int类型占4个字节等等;

对齐填充

为了字节对齐,填充的数据。不是必须的,因为对齐了就不用填充了。

对象可以有对齐数据也可以没有。默认情况下,Java虚拟机堆中对象的起始地址需要对齐至8的倍数。如果一个对象用不到8N个字节则需要对其填充,以此来补齐对象头和实例数据占用内存之后剩余的空间大小。如果对象头和实例数据已经占满了JVM所分配的内存空间,那么就不用再进行对齐填充了。

所有的对象分配的字节总SIZE需要是8的倍数,如果前面的对象头和实例数据占用的总SIZE不满足要求,则通过对齐数据来填满。

为什么要对齐数据?字段内存对齐的其中一个原因,是让字段只出现在同一CPU的缓存行中。如果字段不是对齐的,那么就有可能出现跨缓存行的字段。也就是说,该字段的读取可能需要替换两个缓存行,而该字段的存储也会同时污染两个缓存行。这两种情况对程序的执行效率而言都是不利的。其实对其填充的最终目的是为了计算机高效寻址。

汇总图

在这里插入图片描述

java对象的内存布局实例演示

下面写的测试代码主要打印两个对象的内存布局。一个是普通对象student,一个是数据对象strings。

代码如下:

  • 引入java内存对象的工具包
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud-demo</artifactId>
        <groupId>org.ludengke</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>study</artifactId>
<dependencies>

    <dependency>
        <groupId>org.openjdk.jol</groupId>
        <artifactId>jol-core</artifactId>
        <version>0.9</version>
    </dependency>
</dependencies>

</project>
  • 测试类
package binary;

import org.openjdk.jol.info.ClassLayout;

/**
 * @author ludengke
 * @title: TestObjectStruct
 * @projectName springcloud-demo
 * @description: 测试java对象的内存布局
 * @date 2021/12/1922:07
 */
public class TestObjectStruct {
    static Student student = new Student();
    static String[] strings={"1","sdfsdf","232"};

    /**
     * 查看对象内部信息: ClassLayout.parseInstance(obj).toPrintable()
     * 查看对象外部信息:包括引用的对象:GraphLayout.parseInstance(obj).toPrintable()
     * 查看对象占用空间总大小:GraphLayout.parseInstance(obj).totalSize()
     * @param args
     */
    public static void main(String[] args) {
        System.out.println("student的结构:");
        System.out.println(student.hashCode());//对象的hashcode
        System.out.println(Integer.toHexString(student.hashCode()));//hashcode的16进制
        System.out.println(ClassLayout.parseInstance(student).toPrintable());//打印java对象内存布局
        System.out.println("strings的结构:");
        System.out.println(strings.hashCode());//对象的hashcode
        System.out.println(Integer.toHexString(strings.hashCode()));//hashcode的16进制
        System.out.println(ClassLayout.parseInstance(strings).toPrintable());//打印java对象内存布局

    }
}

  • 执行结果
    在这里插入图片描述

  • 结果解析

这张图是64位虚拟机,未进行指针压缩的执行结果。

图中输出了两个对象,一个是普通对象的student对象,一个是数组对象strings对象。数组对象中多了数组长度。

student对象的说明信息比较多,详细说明了对象头、实例数据、填充数据。可以由于图片篇幅有限,将前8位的说明画到string对象中。

为什么图片中的说明与上面《64位jvm的markword存储》图片的顺序不一致呢,正好是倒序?
这是涉及到一个知识点大端存储与小端存储,这里不详细叙述。我们这里之所以倒序,是因为大端存储的原因。

其它锁状态的验证有空再研究。

参考博客:
https://blog.csdn.net/baidu_28523317/article/details/104453927
https://www.cnblogs.com/jajian/p/13681781.html

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-12-24 18:44:08  更:2021-12-24 18:46:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 17:39:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码