java JUC并发编程 第九章 对象内存布局与对象头

这篇具有很好参考价值的文章主要介绍了java JUC并发编程 第九章 对象内存布局与对象头。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

系列文章目录

第一章 java JUC并发编程 Future: link
第二章 java JUC并发编程 多线程锁: link
第三章 java JUC并发编程 中断机制: link
第四章 java JUC并发编程 java内存模型JMM: link
第五章 java JUC并发编程 volatile与JMM: link
第六章 java JUC并发编程 CAS: link
第七章 java JUC并发编程 原子操作类增强: link
第八章 java JUC并发编程 ThreadLocal: link
第九章 java JUC并发编程 对象内存布局与对象头: link
第十章 java JUC并发编程 Synchronized与锁升级: link
第十一章 java JUC并发编程 AbstractQueuedSynchronizer之AQS: link



1 概述

1.1 对象的内存布局

java JUC并发编程 第九章 对象内存布局与对象头,java,开发语言
java JUC并发编程 第九章 对象内存布局与对象头,java,开发语言
对象内部结构分为:对象头、实例数据、对齐填充(保证8个字节的倍数)
对象头分为对象标记(markOop)和类元信息(klassOop),类元信息存储的是指向改对象类元数据(klass)的首地址。

1.1.1 对象头

1.1.1.1 对象标记Mark Work

java JUC并发编程 第九章 对象内存布局与对象头,java,开发语言
java JUC并发编程 第九章 对象内存布局与对象头,java,开发语言
java JUC并发编程 第九章 对象内存布局与对象头,java,开发语言
默认存储对象的HashCode、分代年龄和锁标志位等信息。这些信息都是与对象自身定义无关的数据,所以MarkWord被设计成一个非固定的数据结构以便在极小的空间内存存储尽量多的数据。它会根据对象的状态复用自己的存储空间,也就说在运行期间MarkWord里存储的数据会随着锁标志位的变化而变化

1.1.1.2 类元信息/类型指针

java JUC并发编程 第九章 对象内存布局与对象头,java,开发语言
类型指针是对象头的一部分,主要指向方法区的Customer的Klass类元信息,虚拟机通过这个指针来确定这个对象是哪个类的实例。

1.1.1.3 对象头大小

64位系统中,Mark Word 占了8个字节,类型指针占了8个字节,一共是16个字节。

1.1.2 实例数据

存放类的属性(Field)数据信心,包括父类的属性和信息

1.1.3 对齐填充

虚拟机要求对象起始地址必须是8字节的整数倍。填充数据不是必须存在的,仅仅是为了字节对齐这部分内存按8字节补充对齐。
只有一个对象头的实例对象,16字节(忽略压缩指针的影响),int 类型占4字节,boolean类型占1字节 -->对齐填充,24字节

2 对象头MarkWord

2.1 32位的了解一下

java JUC并发编程 第九章 对象内存布局与对象头,java,开发语言

2.2 64位

java JUC并发编程 第九章 对象内存布局与对象头,java,开发语言
java JUC并发编程 第九章 对象内存布局与对象头,java,开发语言
markword(64位)分布图,对象布局、GC回收和后面的锁升级就是对象标记MarkWord里面标志位的变化

3 工具展现 Object obj = new Object();

3.1 JOL证明

JOL官网:http://openjdk.java.net/projects/code-tools/jol/
图形化以代码的形式展现一个对象在64位的虚拟机里面MarkWord、实例数据栈的大小、对齐填充
java JUC并发编程 第九章 对象内存布局与对象头,java,开发语言
大意是:java对象的展现,是一个非常小巧的java对象的展现工具,可以给你提供分析对象的布局在java的虚拟机里面。
要使用的话需要引入pom
java JUC并发编程 第九章 对象内存布局与对象头,java,开发语言

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

3.2 代码

package com.atguigu.springcloud.util.interrup;

import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.vm.VM;

public class JOLDemo {
    public static void main(String[] args) {
        //Thread.currentThread
//        System.out.println(VM.current().details());
        /**
         * 上面输出到控制台的内容
         *
         * # Running 64-bit HotSpot VM.                             //64位HotSpot的虚拟机
         * # Using compressed oop with 3-bit shift.                 //压缩的oop
         * # Using compressed klass with 3-bit shift.               //压缩的类型
         * # Objects are 8 bytes aligned.                           //按照8字节对齐
         * # Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes] //文件大小
         * # Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes] //元素大小
         */

        //对象的对齐数
//        System.out.println(VM.current().objectAlignment());
        /**
         * 上面输出到控制台的内容
         * 8
         */

        Object o = new Object();
        //                              转换这个实例
//        System.out.println(ClassLayout.parseInstance(o).toPrintable());
        /**
         * 上面ClassLayout.parseInstance(o).toPrintable()输出到控制台的内容:
         *
         * java.lang.Object object internals: //内部信息的描述
         *  OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
         *       0(开始)4(结束)  (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
         *       4(上4) 4      (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
         *       8     4        (object header)                           e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
         *      12     4        (loss due to the next object alignment(丢失以后为下个对象进行补齐))
         * Instance size: 16 bytes  //结论:new 一个Object的默认大小就是16bytes
         * Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
         */

        //运行的时候先注释掉Customer中的两个属性
//        Customer c1 = new Customer();
//        System.out.println(ClassLayout.parseInstance(c1).toPrintable());
        /**
         * 上面的ClassLayout.parseInstance(c1).toPrintable()输出结果: 默认也是16字节和上面的object对象一样
         * //对象头Customer的内部结构
         * com.atguigu.springcloud.util.interrup.Customer object internals:
         *  OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
         *       0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
         *       4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
         *       8     4        (object header)                           43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)
         *      12     4        (loss due to the next object alignment)
         * Instance size: 16 bytes
         * Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
         */

        /**
         * 上面有个问题为什么类型指针是4字节?
         */

        //运行的时候注意需要有int 和 bolean 两个属性
        Customer c2 = new Customer();
        System.out.println(ClassLayout.parseInstance(c2).toPrintable());

        /**
         * 上面输出ClassLayout.parseInstance(c2).toPrintable()运行结果:
         *
         * com.atguigu.springcloud.util.interrup.Customer object internals:
         *  OFFSET  SIZE      TYPE DESCRIPTION                               VALUE
         *       0     4           (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
         *       4     4           (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
         *       8     4           (object header)                           43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253)
         * //4位                   Customer对象描述                          初始值
         *      12     4       int Customer.id                               0
         * //boolean是 1位                                                  初始值
         *      16     1   boolean Customer.flag                             false
         *           补7位到8的倍数24
         *      17     7           (loss due to the next object alignment)
         * Instance size: 24 bytes
         * Space losses: 0 bytes internal + 7 bytes external = 7 bytes total
         */
    }
}
//只有一个对象头的实例对象,16字节(忽略压缩指针的影响)+4字节+1字节=21字节---->对齐填充,24字节
class Customer{
    //1.第一种情况,只有对象头,没有其他任务数据实例

    //2.第二种情况,int + boolean,满足对齐填充24字节
    int id;
    boolean flag =false;

}
//JOL=java object layOut

java JUC并发编程 第九章 对象内存布局与对象头,java,开发语言
java JUC并发编程 第九章 对象内存布局与对象头,java,开发语言

3.3 GC年龄采用4位bit存储,最大为15,

例如MaxTenuringThreshold参数默认值就是15
为什么是15 因为64位虚拟机表示分代年龄的大小是4bit.所以最大就是2进制的四个1(1111)就是15

java JUC并发编程 第九章 对象内存布局与对象头,java,开发语言

3.3.1 实例证明

1.编辑JVM虚拟机的分代年龄参数:-XX:MaxTenuringThreshold=16
如果不指定上面的的参数默认就是15,必须要小于15,为了演示写成16
java JUC并发编程 第九章 对象内存布局与对象头,java,开发语言
2.运行上面的代码
结果连虚拟机都不能创建
java JUC并发编程 第九章 对象内存布局与对象头,java,开发语言

3.4 压缩指针相关命令说明

打印出启动时的全部参数
java -XX:+PrintCommandLineFlags -version
默认开启压缩说明:
1.初始化堆内存 2.最大堆内存 4.压缩过类型指针(可以解释前面的为什么类型指针为4的问题)
java JUC并发编程 第九章 对象内存布局与对象头,java,开发语言
手动关闭压缩再看看
-XX:-UseCompressedClassPointers
java JUC并发编程 第九章 对象内存布局与对象头,java,开发语言
java JUC并发编程 第九章 对象内存布局与对象头,java,开发语言
没有对齐填充直接到16字节
不管是否压缩指针,只有一个对象头的话都是16字节
java JUC并发编程 第九章 对象内存布局与对象头,java,开发语言文章来源地址https://www.toymoban.com/news/detail-726168.html

到了这里,关于java JUC并发编程 第九章 对象内存布局与对象头的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 《TCP IP网路编程》第九章

            我们进行套接字编程时往往只关注数据通信,而忽略了 套接字具有的不同特性 。但是,理解这些特性并根据实际需要进行更改也很重要。下面列出了一些 套接字可选项 。         从表中可以看出,套接字可选项是分层的。 IPPROTO_IP 可选项是IP协议相关事项

    2024年02月16日
    浏览(38)
  • 【并发编程】JUC并发编程(彻底搞懂JUC)

    如果你对多线程没什么了解,那么从入门模块开始。 如果你已经入门了多线程(知道基础的线程创建、死锁、synchronized、lock等),那么从juc模块开始。 新手学技术、老手学体系,高手学格局。 JUC实际上就是我们对于jdk中java.util .concurrent 工具包的简称 ,其结构如下: 这个包

    2024年02月20日
    浏览(51)
  • 《Opencv3编程入门》学习笔记—第九章

    记录一下在学习《Opencv3编程入门》这本书时遇到的问题或重要的知识点。 一、图像直方图概述 1、作用:   在每个兴趣点设置一个有相近特征的直方图所构成的标签,通过标记帧与帧之间显著的边缘、颜色、角度等特征的统计变化,来检测视频中场景的变化。 2、概念:

    2024年02月11日
    浏览(48)
  • 创造与布局:剖析 Java 对象创建过程以及内存布局

    目录 上下文提及到了类的加载过程,详细介绍了加载类的每个阶段:Loading、Linking、Initialize,在其中也说明了静态变量赋值顺序 先赋予默认值、在 Initialize 初始化阶段赋予初始值 从类加载到双亲委派:深入解析类加载机制与 ClassLoader 该篇文章会详细实例对象的创建过程、对

    2024年02月11日
    浏览(38)
  • 一看就懂的java对象内存布局

    前言 Java 中一切皆对象,同时对象也是 Java 编程中接触最多的概念,深入理解 Java 对象能够更帮助我们深入地掌握 Java 技术栈。在这篇文章里,我们将从内存的视角,带你深入理解 Java 对象在虚拟机中的表现形式。 学习路线图: 1. 对象在哪里分配? 在 Java 虚拟机中,Java 堆

    2024年02月05日
    浏览(45)
  • C Primer Plus第九章编程练习答案

    学完C语言之后,我就去阅读《C Primer Plus》这本经典的C语言书籍,对每一章的编程练习题都做了相关的解答,仅仅代表着我个人的解答思路,如有错误,请各位大佬帮忙点出! 1.设计一个函数min(x, y),返回两个double类型值的较小值。在一个简单 的驱动程序中测试该函数。 2

    2024年02月06日
    浏览(42)
  • 深入理解Java虚拟机jvm-对象的内存布局

    在HotSpot虚拟机里,对象在堆内存中的存储布局可以划分为三个部分:对象头(Header)、实例 数据(Instance Data)和对齐填充(Padding)。 HotSpot虚拟机对象的对象头部分包括两类信息。第一类是用于存储对象自身的运行时数据,如哈 希码(HashCode)、GC分代年龄、锁状态标志、

    2024年02月09日
    浏览(56)
  • 曲线艺术编程 coding curves 第九章 旋轮曲线(ROULETTE CURVES)

    原作:Keith Peters https://www.bit-101.com/blog/2022/11/coding-curves/ 译者:池中物王二狗(sheldon) 源码:github: https://github.com/willian12345/coding-curves 曲线艺术编程系列第 9 章 一开始我本章标题我打算使用“次摆线与摆线(旋轮线)”。我想它们是两种不同类型的曲线,虽然有点儿联系。但随

    2024年02月08日
    浏览(43)
  • TCP/IP网络编程 第九章:套接字的多种可选项

    套接字的多种可选项 下列是针对SOL_SOCKET协议层的 可选项 描述 SO_REUSEADDR 允许重用本地地址和端口,即使之前的连接处于 TIME_WAIT 状态。 SO_KEEPALIVE 启用 TCP 连接的心跳检测功能,保持连接活动状态。 SO_LINGER 控制关闭连接时的行为。设置为 0 表示立即关闭连接,非零值则表示

    2024年02月16日
    浏览(47)
  • 第九章:Java常用类

    目录 9.1:字符串相关的类:String         9.1.1:String用法         9.1.2:String方法         9.1.3:String与char[]、byte[]之间的转换         9.1.4:StringBuffer和StringBuilder的使用 9.2:JDK 8之前的日期时间API 9.3:JDK 8中新日期时间API         9.3.1:LocalDate、LocalTime、LocalDateTime的使

    2024年02月09日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包