精华内容
下载资源
问答
  • 2020-05-03:对象头具体包括什么

    千次阅读 2020-06-11 08:22:16
    福哥口诀法:标类长(对象头:markword标记字、klass类型指针、数组长度(仅限于数组)) 无偏轻重G(锁状态:无锁、偏向锁、轻量级锁、重量级锁、GC标记) 未哈未年标,25 31 1 (64位无锁情况:未使用25、hashcode...

    福哥口诀法:标类长(对象头:markword标记字、klass类型指针、数组长度(仅限于数组))

    无偏轻重G(锁状态:无锁、偏向锁、轻量级锁、重量级锁、GC标记)

    未哈未年标,25 31 1 (64位无锁情况:未使用25、hashcode31、未使用1、年龄4、偏向标志1)
    线时未年标,54和2 1(64位偏向锁情况:线程id54、偏向时间戳2、未使用1、年龄4、偏向标志1)

    哈年标25 (32位无锁情况:hashcode25、年龄4、偏向标志1)
    线时年标23 2 (32位偏向锁情况:线程id23、偏向时间戳2、年龄4、偏向标志1)

    评论

    展开全文
  • 包括: identity hashcode GC 锁 比如刚刚的代码,将变量加上一个锁,输出: 可以查看出markword 的值会改变 根据下面的一张图,回答问题 我们能不能将GC年龄调高一点,变成32? 不能,因为分代年龄存储的字节...

    包括:
    identity hashcode
    GC

    在这里插入图片描述

    比如刚刚的代码,将变量加上一个锁,输出:
    可以查看出markword 的值会改变
    在这里插入图片描述

    根据下面的一张图,回答问题 我们能不能将GC年龄调高一点,变成32?
    在这里插入图片描述
    不能,因为分代年龄存储的字节只有4位,只能存储最多16的数据,不可能提高到32

    展开全文
  • HotSpot虚拟机的对象头(Object Header)包括两部分信息,第一部分用于存储对象自身的运行时数据, 如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等等,这部分数据的长度在32...

    目录

    一,对象头

    1,Mark Word

    2,指向类的指针

    3,数组长度

    二,实例数据

    三,对齐填充字节


    Java对象保存在内存中时,由以下三部分组成:

    1,对象头

    2,实例数据

    3,对齐填充字节

    一,对象头

    java的对象头由以下三部分组成:

    1,Mark Word

    2,指向类的指针

    3,数组长度(只有数组对象才有)

     

    1,Mark Word

    Mark Word记录了对象和锁有关的信息,当这个对象被synchronized关键字当成同步锁时,围绕这个锁的一系列操作都和Mark Word有关。

    Mark Word在32位JVM中的长度是32bit,在64位JVM中长度是64bit。

    Mark Word在不同的锁状态下存储的内容不同,在32位JVM中是这么存的:

    锁状态

    25bit

    4bit

    1bit

    2bit

    23bit

    2bit

    是否偏向锁

    锁标志位

    无锁

    对象的HashCode

    分代年龄

    0

    01

    偏向锁

    线程ID

    Epoch

    分代年龄

    1

    01

    轻量级锁

    指向栈中锁记录的指针

    00

    重量级锁

    指向重量级锁的指针

    10

    GC标记

    11

    其中无锁和偏向锁的锁标志位都是01,只是在前面的1bit区分了这是无锁状态还是偏向锁状态。

    JDK1.6以后的版本在处理同步锁时存在锁升级的概念,JVM对于同步锁的处理是从偏向锁开始的,随着竞争越来越激烈,处理方式从偏向锁升级到轻量级锁,最终升级到重量级锁。

     

    JVM一般是这样使用锁和Mark Word的:

    1,当没有被当成锁时,这就是一个普通的对象,Mark Word记录对象的HashCode,锁标志位是01,是否偏向锁那一位是0。

    2,当对象被当做同步锁并有一个线程A抢到了锁时,锁标志位还是01,但是否偏向锁那一位改成1,前23bit记录抢到锁的线程id,表示进入偏向锁状态。

    3,当线程A再次试图来获得锁时,JVM发现同步锁对象的标志位是01,是否偏向锁是1,也就是偏向状态,Mark Word中记录的线程id就是线程A自己的id,表示线程A已经获得了这个偏向锁,可以执行同步锁的代码。

    4,当线程B试图获得这个锁时,JVM发现同步锁处于偏向状态,但是Mark Word中的线程id记录的不是B,那么线程B会先用CAS操作试图获得锁,这里的获得锁操作是有可能成功的,因为线程A一般不会自动释放偏向锁。如果抢锁成功,就把Mark Word里的线程id改为线程B的id,代表线程B获得了这个偏向锁,可以执行同步锁代码。如果抢锁失败,则继续执行步骤5。

    5,偏向锁状态抢锁失败,代表当前锁有一定的竞争,偏向锁将升级为轻量级锁。JVM会在当前线程的线程栈中开辟一块单独的空间,里面保存指向对象锁Mark Word的指针,同时在对象锁Mark Word中保存指向这片空间的指针。上述两个保存操作都是CAS操作,如果保存成功,代表线程抢到了同步锁,就把Mark Word中的锁标志位改成00,可以执行同步锁代码。如果保存失败,表示抢锁失败,竞争太激烈,继续执行步骤6。

    6,轻量级锁抢锁失败,JVM会使用自旋锁,自旋锁不是一个锁状态,只是代表不断的重试,尝试抢锁。从JDK1.7开始,自旋锁默认启用,自旋次数由JVM决定。如果抢锁成功则执行同步锁代码,如果失败则继续执行步骤7。

    7,自旋锁重试之后如果抢锁依然失败,同步锁会升级至重量级锁,锁标志位改为10。在这个状态下,未抢到锁的线程都会被阻塞。

     

    2,指向类的指针

    该指针在32位JVM中的长度是32bit,在64位JVM中长度是64bit。

    Java对象的类数据保存在方法区。

     

    3,数组长度

    只有数组对象保存了这部分数据。

    该数据在32位和64位JVM中长度都是32bit。

     

    二,实例数据

    对象的实例数据就是在java代码中能看到的属性和他们的值。

     

    三,对齐填充字节

    因为JVM要求java的对象占的内存大小应该是8bit的倍数,所以后面有几个字节用于把对象的大小补齐至8bit的倍数,没有特别的功能。

     

    一:对象头

    HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。  

    HotSpot虚拟机的对象头(Object Header)包括两部分信息,第一部分用于存储对象自身的运行时数据, 如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等等,这部分数据的长度在32位和64位的虚拟机(暂 不考虑开启压缩指针的场景)中分别为32个和64个Bits,官方称它为“Mark Word”。

    对象需要存储的运行时数据很多,其实已经超出了32、64位Bitmap结构所能记录的限度,但是对象头信息是与对象自身定义的数据无关的额 外存储成本,考虑到虚拟机的空间效率,Mark Word被设计成一个非固定的数据结构以便在极小的空间内存储尽量多的信息,它会根据对象的状态复用自己的存储空间。例如在32位的HotSpot虚拟机 中对象未被锁定的状态下,Mark Word的32个Bits空间中的25Bits用于存储对象哈希码(HashCode),4Bits用于存储对象分代年龄,2Bits用于存储锁标志 位,1Bit固定为0,在其他状态(轻量级锁定、重量级锁定、GC标记、可偏向)下对象的存储内容如下表所示。  

    对象头的另外一部分是类型指针,即是对象指向它的类的元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。并不是所有的虚拟机实现都必须在对象数据上保留类型指针,换句话说查找对象的元数据信息并不一定要经过对象本身。另外,如果对象是一个Java数组,那在对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通Java对象的元数据信息确定Java对象的大小,但是从数组的元数据中无法确定数组的大小。  

     

    这里要特别关注的是锁标志位,  锁标志位与是否偏向锁对应到唯一的锁状态。

    所以锁的状态保存在对象头中,所以再理解

     

    1. Synchronized锁的到底是什么, 锁住的是代码还是对象)(答案锁的是对象)?
    2.  java中锁,锁的是对象,它是怎么实现的?

     

    这两个问题,就好懂了!

     

    二:锁的状态

    锁的状态总共有四种:无锁状态、偏向锁、轻量级锁和重量级锁。随着锁的竞争,锁可以从偏向锁升级到轻量级锁,再升级的重量级锁(但是锁的升级是单向的,也就是说只能从低到高升级,不会出现锁的降级)。JDK 1.6中默认是开启偏向锁和轻量级锁的,我们也可以通过-XX:-UseBiasedLocking来禁用偏向锁。

     

    1、轻量级锁的加锁过程

      (1)在代码进入同步块的时候,如果同步对象锁状态为无锁状态(锁标志位为“01”状态,是否为偏向锁为“0”),虚拟机首先将在当前线程的栈帧中建立一个名为锁记录(Lock Record)的空间,用于存储锁对象目前的Mark Word的拷贝,官方称之为 Displaced Mark Word。这时候线程堆栈与对象头的状态如图2.1所示。

      (2)拷贝对象头中的Mark Word复制到锁记录中。

      (3)拷贝成功后,虚拟机将使用CAS操作尝试将对象的Mark Word更新为指向Lock Record的指针,并将Lock record里的owner指针指向object mark word。如果更新成功,则执行步骤(4),否则执行步骤(5)。

      (4)如果这个更新动作成功了,那么这个线程就拥有了该对象的锁,并且对象Mark Word的锁标志位设置为“00”,即表示此对象处于轻量级锁定状态,这时候线程堆栈与对象头的状态如图2.2所示。

      (5)如果这个更新操作失败了,虚拟机首先会检查对象的Mark Word是否指向当前线程的栈帧,如果是就说明当前线程已经拥有了这个对象的锁,那就可以直接进入同步块继续执行。否则说明多个线程竞争锁,轻量级锁就要膨胀为重量级锁,锁标志的状态值变为“10”,Mark Word中存储的就是指向重量级锁(互斥量)的指针,后面等待锁的线程也要进入阻塞状态。 而当前线程便尝试使用自旋来获取锁,自旋就是为了不让线程阻塞,而采用循环去获取锁的过程。

     

      图2.1 轻量级锁CAS操作之前堆栈与对象的状态

     

    图2.2 轻量级锁CAS操作之后堆栈与对象的状态

     

     

    三、偏向锁

      引入偏向锁是为了在无多线程竞争的情况下尽量减少不必要的轻量级锁执行路径,因为轻量级锁的获取及释放依赖多次CAS原子指令,而偏向锁只需要在置换ThreadID的时候依赖一次CAS原子指令(由于一旦出现多线程竞争的情况就必须撤销偏向锁,所以偏向锁的撤销操作的性能损耗必须小于节省下来的CAS原子指令的性能消耗)。上面说过,轻量级锁是为了在线程交替执行同步块时提高性能,而偏向锁则是在只有一个线程执行同步块时进一步提高性能。

    1、偏向锁获取过程:

      (1)访问Mark Word中偏向锁的标识是否设置成1,锁标志位是否为01——确认为可偏向状态。

      (2)如果为可偏向状态,则测试线程ID是否指向当前线程,如果是,进入步骤(5),否则进入步骤(3)。

      (3)如果线程ID并未指向当前线程,则通过CAS操作竞争锁。如果竞争成功,则将Mark Word中线程ID设置为当前线程ID,然后执行(5);如果竞争失败,执行(4)。

      (4)如果CAS获取偏向锁失败,则表示有竞争。当到达全局安全点(safepoint)时获得偏向锁的线程被挂起,偏向锁升级为轻量级锁,然后被阻塞在安全点的线程继续往下执行同步代码。

      (5)执行同步代码。

    2、偏向锁的释放:

      偏向锁的撤销在上述第四步骤中有提到。偏向锁只有遇到其他线程尝试竞争偏向锁时,持有偏向锁的线程才会释放锁,线程不会主动去释放偏向锁。偏向锁的撤销,需要等待全局安全点(在这个时间点上没有字节码正在执行),它会首先暂停拥有偏向锁的线程,判断锁对象是否处于被锁定状态,撤销偏向锁后恢复到未锁定(标志位为“01”)或轻量级锁(标志位为“00”)的状态。

    3、重量级锁、轻量级锁和偏向锁之间转换

    该图主要是对上述内容的总结,如果对上述内容有较好的了解的话,该图应该很容易看懂。

     

     

     

    参考资料:

    https://blog.csdn.net/lkforce/article/details/81128115?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~all~first_rank_v2~rank_v25-2-81128115.nonecase&utm_term=java%E5%AF%B9%E8%B1%A1%E5%A4%B4%E6%98%AF%E4%BB%80%E4%B9%88

          http://blog.csdn.NET/u010723709/article/details/50341631

          http://www.cnblogs.com/paddix/p/5405678.html

          http://www.cnblogs.com/lingepeiyong/archive/2012/10/30/2745973.html

    展开全文
  • 问题1、请解释一下对象的创建过程? class loading class linking verification preparation resolution class initializing 静态初始化的过程 申请对象内存 成员变量赋默认值 调用构造方法<init>...

     上一篇:【深入理解JVM】3、CPU储存器+MESI+CPU伪共享+CPU乱序问题及代码论证【面试必备】

     

    问题1、请解释一下对象的创建过程?

    1. class loading
    2. class linking
      1. verification
      2. preparation
      3. resolution
    3. class initializing 静态初始化的过程
    4. 申请对象内存
    5. 成员变量赋默认值
    6. 调用构造方法<init>
      1. 成员变量顺序赋初始值
      2. 执行构造方法语句:首先去调用super

    问题2、对象在内存中的存储布局?

    1、先说一下观察虚拟机配置的命令:

    java -XX:+PrintCommandLineFlags -version

    idea的设置:

    在虚拟机执行命令的效果:

    C:\Users\zhouwei>java -XX:+PrintCommandLineFlags -version
    -XX:InitialHeapSize=266984512 初始的堆大小
    -XX:MaxHeapSize=4271752192 最大的堆大小
    -XX:+PrintCommandLineFlags 
    -XX:+UseCompressedClassPointers:(默认时压缩的,把+号改成-号就不再压缩) 
    -XX:+UseCompressedOops(oops):普通对象的指针 ordinary object pointers比如引用的string见下
    -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
    java version "1.8.0_161"
    Java(TM) SE Runtime Environment (build 1.8.0_161-b12)
    Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)

     2、普通对象

    注释:有些地方是Klass Pointer有些又是

    内存里的一个Java对象分为三部分:对象头,实例数据,对齐

    • 对象头:markword  8Bytes 用于标记锁信息、GC信息、IdentityHashCode等。
    • class Pointer 类指针:jvm开启内存压缩(-XX:+UseCompressedClassPointer),4字节。不开启,8字节。默认开启,用于标记该对象是哪个Class的实例 例如:Object.class。
    • 实例数据(instance data):包括对象的所有成员变量,大小由各个成员变量决定,如果没有成员变量,则这一块为空,基本类型 (int,float 4字节 long,double 8字节,char,short 2字节,byte 1字节 ,boolean 实际大小1bit  占用1字节)。
      • 引用类型:-XX:+UseCompressedOops 为4字节 不开启为8字节 , Oops Ordinary Object Pointers
    •  Padding对齐:8的倍数(因为读取的时候不是按直接读的,是读的块,一般是8个字节的倍数,这样效率会更高)

     3、数组对象

    • 对象头:markword  8Bytes 用于标记锁信息、GC信息、IdentityHashCode等
    • class Pointer 类指针:jvm开启内存压缩(-XX:+UseCompressedClassPointer),4字节。不开启,8字节。默认开启,用于标记该对象是哪个Class的实例 例如:Object.class
    • 数组长度:4字节 标记数组有多少个元素
    • 数组数据(instance data):根据数组类型m和长度n而定,长度为m*n
            如果元素为基本类型,比如byte/boolean/short/char/int/long/double,则m为对应的长度;
            如果元素为数组, m是4字节的引用
            如果数组长度为0,这一块为空
    • padding对齐:一个对象占用的字节数必须是8的倍数,不足的用padding对齐

     实验:利用java agent(class文件到内存之间的代理,这个代理得自己去实现)的机制。下面补充了种用JOL工具的,比较简单。

    1、创建文件ObjectSizeAgent(类似到内存前有个代理)

    public class ObjectSizeAgent {
        // 类似调弦的作用
        private static Instrumentation inst;
    
        public static void premain(String agentArgs, Instrumentation _inst) {
            inst = _inst;
        }
    
        public static long sizeOf(Object o) {
            return inst.getObjectSize(o);
        }
    }
    

    2、src目录下创建META-INF/MANIFEST.MF

    这里可以只要Premain-Class: com.mashibing.jvm.agent.ObjectSizeAgent

    Manifest-Version: 1.0
    Created-By: mashibing.com
    Premain-Class: com.mashibing.jvm.agent.ObjectSizeAgent

    3、打包jar文件

    4、在需要使用该Agent Jar的项目中引入该Jar包 project structure - project settings - library 添加该jar包

    5、运行时需要该Agent Jar的类,加入参数:

    执行用哪个jar文件当作代理来运行我的虚拟机:

    -javaagent:C:\work\ijprojects\ObjectSize\out\artifacts\ObjectSize_jar\ObjectSize.jar

    6、如何使用该类:

    测出来 object:16个字节 object分析:

    对象头是8个字节,本来应该是8个字节(64位的)因为默认打开时压缩的,被压缩成4个字节(class_pointer ),

    所有整个object对象时8+4=12个字节,测出来时16个字节,因为后面有个padding(对齐)4个字节。

    8+4+padding

    数组分析:

    对象头8个字节+ class_pointer (网上很多把这里写成OOPS,这是错误的)压缩4个字节,长度4个字节 =16个字节。

    -XX:+UseCompressedClassPointers把+号改成-号不压缩了,数组就变成了24个字节。

    对象头8个字节+class_pointer 没压缩 8个字节 +长度4个字节+paddding 4个字节 =24个字节

    注释:A:-XX:+UseCompressedOops(oops):普通对象的指针 ordinary object pointers比如引用的String见下

               B:-XX:+UseCompressedClassPointers:(默认时压缩的,把+号改成-号就不再压缩) 

    public class T03_SizeOfAnObject {
        public static void main(String[] args) {
             // ObjectSizeAgent这个jar包是自己生成的。
            System.out.println(ObjectSizeAgent.sizeOf(new Object()));
            System.out.println(ObjectSizeAgent.sizeOf(new int[] {}));
            System.out.println(ObjectSizeAgent.sizeOf(new P()));
        }
    
        // 一个Object占多少个字节
        // -XX:+UseCompressedClassPointers -XX:+UseCompressedOops
        // Oops = ordinary object pointers
        private static class P {
                            //8 _markword
                            //4 _class pointer
            int id;         //4
            String name;    //4
            int age;        //4
    
            byte b1;        //1
            byte b2;        //1
    
            Object o;       //4
            byte b3;        //1
    
        }
    }

     Hotspot开启内存压缩的规则(64位机)

    1. 4G以下,直接砍掉高32位2. 4G - 32G,默认开启内存压缩 ClassPointers Oops3. 32G,压缩无效,使用64位   内存并不是越大越好(^-^)

    3、对象头包括什么?

    1.8的实现,C++文件,去看Hotspot源码。(很复杂)

    知道几点就行了(听过就行了):

    关于锁状态详情可以参考这篇文章:【Java对象解析】不得不了解的对象头

    HotSpot虚拟机的对象头(Object Header)包括两部分信息,第一部分用于存储对象自身的运行时数据, 如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等等,这部分数据的长度在32位和64位的虚拟机(暂 不考虑开启压缩指针的场景)中分别为32个和64个Bits,官方称它为“Mark Word”。

    对象需要存储的运行时数据很多,其实已经超出了32、64位Bitmap结构所能记录的限度,但是对象头信息是与对象自身定义的数据无关的额 外存储成本,考虑到虚拟机的空间效率,Mark Word被设计成一个非固定的数据结构以便在极小的空间内存储尽量多的信息,它会根据对象的状态复用自己的存储空间。例如在32位的HotSpot虚拟机 中对象未被锁定的状态下,Mark Word的32个Bits空间中的25Bits用于存储对象哈希码(HashCode),4Bits用于存储对象分代年龄,2Bits用于存储锁标志 位,1Bit固定为0,在其他状态(轻量级锁定、重量级锁定、GC标记、可偏向)下对象的存储内容如下表所示。  

     

    对象头的另外一部分是类型指针,即是对象指向它的类的元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。并不是所有的虚拟机实现都必须在对象数据上保留类型指针,换句话说查找对象的元数据信息并不一定要经过对象本身。另外,如果对象是一个Java数组,那在对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通Java对象的元数据信息确定Java对象的大小,但是从数组的元数据中无法确定数组的大小。  

    锁标志位与是否偏向锁对应到唯一的锁状态

    锁的状态总共有四种:无锁状态、偏向锁、轻量级锁和重量级锁。

    偏向锁:(启用参数-XX:+UseBiasedLocking,这是JDK 1.6的默认值)为了让线程获得锁的代驾更低而引入了偏向锁,那么,“锁总是同一个线程持有,很少发生竞争”,也就是说锁总是被第一个占用他的线程拥有,这个线程就是锁的偏向线程。那么只需要在锁第一次被拥有的时候,记录下偏向线程ID。这样偏向线程就一直持有着锁,直到竞争发生才释放锁。以后每次同步,检查锁的偏向线程ID与当前线程ID是否一致,如果一致直接进入同步,退出同步也,无需每次加锁解锁都去CAS更新对象头,如果不一致意味着发生了竞争,锁已经不是总是偏向于同一个线程了,这时候需要锁膨胀为轻量级锁,才能保证线程间公平竞争锁。乐观锁。

    轻量级锁:还没有涉及到内核。获取轻量锁的过程与偏向锁不同,竞争锁的线程首先需要拷贝对象头中的Mark Word到帧栈的锁记录中。拷贝成功后使用CAS操作尝试将对象的Mark Word更新为指向当前线程的指针。如果这个更新动作成功了,那么这个线程就拥有了该对象的锁。如果更新失败,那么意味着有多个线程在竞争。

    • 轻量级锁每次退出同步块都需要释放锁,而偏向锁是在竞争发生时才释放锁
    • 每次进入退出同步块都需要CAS更新对象头
    • 争夺轻量级锁失败时,自旋尝试抢占锁

    重量级锁:有涉及到内核。消耗的资源比较高。重量级锁的加锁、解锁过程和轻量级锁差不多,区别是:竞争失败后,线程阻塞,释放锁后,唤醒阻塞的线程,不使用自旋锁,不会那么消耗CPU,所以重量级锁适合用在同步块执行时间长的情况下。随着锁的竞争,锁可以从偏向锁升级到轻量级锁,再升级的重量级锁(但是锁的升级是单向的,也就是说只能从低到高升级,不会出现锁的降级)。JDK 1.6中默认是开启偏向锁和轻量级锁的,我们也可以通过-XX:-UseBiasedLocking来禁用偏向锁。

    对象的hashCode平时不是在25bit那,只有调用的时候才会被标记。

    hashcode还比较特殊:(没搞懂)

    • 对象的hashcode方法被重写:按原始内容计算的hashcode,重写过的hashcode方法计算的结果不会存在这里。
    • 对象的hashcode没有被重写:那么默认是调用os:random产生的hashcode,可以通过System.identityHashCode获取;os:random产生hashcode的规则为:next——rand=(16807seed)mod(2*31-1),因此可以使用31位存储另外一旦生成了hashcode,JVM会将其记录在markword中。称之为identityHashCode。

    什么时候回产生hashcode?

    • 调用未重写的hashcode方法以及system.identityHashCode的时候。

    有两个位置是标记GC的。

    为什么GC年龄默认为15?

    • 因为分代年龄头只有4位,最大为15.(有人说这个数能调,扯淡的)

    markword 64位 8个字节

    只找到32位的图

    当一个对象计算过identityHashCode之后,不能进入偏向锁状态?

    因为计算过hashcode,前25位就已经被占用了,所以无法进入偏向锁状态。

    感兴趣可以参考:

    死磕Synchronized底层实现,面试你还怕什么?

    面试题深入解析:Synchronized底层实现

    死磕Synchronized底层实现--重量级锁

    一文让你读懂Synchronized底层实现,秒杀面试官

     

    4、对象定位

    参考《深入理解JAVA虚拟机》

    T t = new T();t是怎么找到实际new出来的对象的?

    1、句柄池:

    • 效率相对较低,稳定
    • 但是在GC(三色标记算法)垃圾回收的时候效率会比较高。
    • 使用句柄访最大的好处是reference中存储着稳定的句柄地址,当对象移动之后(垃圾收集时移动对象是非常普遍的行为),只需要改变句柄中的对象实例地址即可,reference不用修改。

    2、直接指针:

    • 访问速度快,它减少了一次指针定位的时间开销,由于java是面向对象的语言,在开发中java对象的访问非常的频繁,因此这类开销积少成多也是非常可观的,反之则提升访问速度。

     

     

    补充:利用JOL工具JOL工具及其分析对象在JVM的大小和分布代替之前的java agent方式。

    JOL全称为Java Object Layout,是分析JVM中对象布局的工具,该工具大量使用了Unsafe、JVMTI来解码布局情况,所以分析结果是比较精准的。通常分析java对象的大小需要人工按照Java基础数据类型大小及内容大小估算出缓存对象的大概堆占用,但是麻烦还不准。而OpenJDK,提供了JOL包,可以帮我们在运行时计算某个对象的大小,是非常好的工具。

    应用:分析对象在JVM的大小和分布

    依赖

    <!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-core -->
    <dependency>
        <groupId>org.openjdk.jol</groupId>
        <artifactId>jol-core</artifactId>
        <version>0.10</version>
    </dependency>
    /**
     * @author zhouwei
     * @date
     */
    
    public class JolDemo {
    
        static Object generate() {
            Map<String, Object> map = new HashMap<>();
            map.put("a", new Integer(1));
            map.put("b", "b");
            map.put("c", new Date());
    
            for (int i = 0; i < 10; i++) {
                map.put(String.valueOf(i), String.valueOf(i));
            }
            return map;
        }
    
        static void print(String message) {
            System.out.println(message);
            System.out.println("-------------------------");
        }
    
        public static void main(String[] args) {
            Object obj = generate();
    
            // 查看对象内部信息
            print("查看对象内部信息:"+ClassLayout.parseInstance(obj).toPrintable());
    
            // 查看对象外部信息:包括引用的对象
            print("查看对象外部信息:包括引用的对象"+GraphLayout.parseInstance(obj).toPrintable());
    
            // 查看对象占用空间总大小
            print("查看对象占用空间总大小size : " + GraphLayout.parseInstance(obj).totalSize());
        }
    
    }

     打印结果:

    查看对象内部信息:java.util.HashMap 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)                           a8 37 00 f8 (10101000 00110111 00000000 11111000) (-134203480)
         12     4              java.util.Set AbstractMap.keySet                        null
         16     4       java.util.Collection AbstractMap.values                        null
         20     4                        int HashMap.size                              13
         24     4                        int HashMap.modCount                          13
         28     4                        int HashMap.threshold                         24
         32     4                      float HashMap.loadFactor                        0.75
         36     4   java.util.HashMap.Node[] HashMap.table                             [null, (object), (object), (object), null, null, null, null, null, null, null, null, null, null, null, null, (object), (object), (object), (object), (object), (object), (object), (object), (object), (object), null, null, null, null, null, null]
         40     4              java.util.Set HashMap.entrySet                          null
         44     4                            (loss due to the next object alignment)
    Instance size: 48 bytes
    Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
    
    -------------------------
    查看对象外部信息:包括引用的对象java.util.HashMap@10dba097d object externals:
              ADDRESS       SIZE TYPE                      PATH                           VALUE
            76b7302b0         48 java.util.HashMap                                        (object)
            76b7302e0         24 java.lang.String          .table[1].key                  (object)
            76b7302f8         24 [C                        .table[1].key.value            [a]
            76b730310       2112 (something else)          (somewhere else)               (something else)
            76b730b50         16 java.lang.Integer         .table[1].value                1
            76b730b60         80 (something else)          (somewhere else)               (something else)
            76b730bb0         32 java.util.HashMap$Node    .table[1]                      (object)
            76b730bd0         24 java.lang.String          .table[2].key                  (object)
            76b730be8         24 [C                        .table[2].key.value            [b]
            76b730c00         32 java.util.HashMap$Node    .table[2]                      (object)
            76b730c20         24 java.lang.String          .table[3].key                  (object)
            76b730c38         24 [C                        .table[3].key.value            [c]
            76b730c50      70760 (something else)          (somewhere else)               (something else)
            76b7420b8         24 java.util.Date            .table[3].value                (object)
            76b7420d0         32 java.util.HashMap$Node    .table[3]                      (object)
            76b7420f0         24 [C                        .table[16].key.value           [0]
            76b742108         24 java.lang.String          .table[16].key                 (object)
            76b742120         24 [C                        .table[16].value.value         [0]
            76b742138         24 java.lang.String          .table[16].value               (object)
            76b742150         32 java.util.HashMap$Node    .table[16]                     (object)
            76b742170         24 [C                        .table[17].key.value           [1]
            76b742188         24 java.lang.String          .table[17].key                 (object)
            76b7421a0         24 [C                        .table[17].value.value         [1]
            76b7421b8         24 java.lang.String          .table[17].value               (object)
            76b7421d0         32 java.util.HashMap$Node    .table[17]                     (object)
            76b7421f0         24 [C                        .table[18].key.value           [2]
            76b742208         24 java.lang.String          .table[18].key                 (object)
            76b742220         24 [C                        .table[18].value.value         [2]
            76b742238         24 java.lang.String          .table[18].value               (object)
            76b742250         32 java.util.HashMap$Node    .table[18]                     (object)
            76b742270         24 [C                        .table[19].key.value           [3]
            76b742288         24 java.lang.String          .table[19].key                 (object)
            76b7422a0         24 [C                        .table[19].value.value         [3]
            76b7422b8         24 java.lang.String          .table[19].value               (object)
            76b7422d0         32 java.util.HashMap$Node    .table[19]                     (object)
            76b7422f0         24 [C                        .table[20].key.value           [4]
            76b742308         24 java.lang.String          .table[20].key                 (object)
            76b742320         24 [C                        .table[20].value.value         [4]
            76b742338         24 java.lang.String          .table[20].value               (object)
            76b742350         32 java.util.HashMap$Node    .table[20]                     (object)
            76b742370         24 [C                        .table[21].key.value           [5]
            76b742388         24 java.lang.String          .table[21].key                 (object)
            76b7423a0         24 [C                        .table[21].value.value         [5]
            76b7423b8         24 java.lang.String          .table[21].value               (object)
            76b7423d0         32 java.util.HashMap$Node    .table[21]                     (object)
            76b7423f0         24 [C                        .table[22].key.value           [6]
            76b742408         24 java.lang.String          .table[22].key                 (object)
            76b742420         24 [C                        .table[22].value.value         [6]
            76b742438         24 java.lang.String          .table[22].value               (object)
            76b742450         32 java.util.HashMap$Node    .table[22]                     (object)
            76b742470         24 [C                        .table[23].key.value           [7]
            76b742488         24 java.lang.String          .table[23].key                 (object)
            76b7424a0         24 [C                        .table[23].value.value         [7]
            76b7424b8         24 java.lang.String          .table[23].value               (object)
            76b7424d0         32 java.util.HashMap$Node    .table[23]                     (object)
            76b7424f0         24 [C                        .table[24].key.value           [8]
            76b742508         24 java.lang.String          .table[24].key                 (object)
            76b742520         24 [C                        .table[24].value.value         [8]
            76b742538         24 java.lang.String          .table[24].value               (object)
            76b742550         32 java.util.HashMap$Node    .table[24]                     (object)
            76b742570         24 [C                        .table[25].key.value           [9]
            76b742588         24 java.lang.String          .table[25].key                 (object)
            76b7425a0         24 [C                        .table[25].value.value         [9]
            76b7425b8         24 java.lang.String          .table[25].value               (object)
            76b7425d0         32 java.util.HashMap$Node    .table[25]                     (object)
            76b7425f0        144 [Ljava.util.HashMap$Node; .table                         [null, (object), (object), (object), null, null, null, null, null, null, null, null, null, null, null, null, (object), (object), (object), (object), (object), (object), (object), (object), (object), (object), null, null, null, null, null, null]
    
    
    -------------------------
    查看对象占用空间总大小size : 1752

    下一篇:【深入理解JVM】5、运行时数据区(Run-time data areas)+常用指令【面试必备】

    展开全文
  • 对象头

    2019-02-18 17:20:49
    HotSpot 上虚拟机的对象头包括两部分信息,第一部分用于存储对象自身的运行时数据。 如哈希码(HashCode也就是为什么java代码取hashcode很快的原因). GC分代年龄、锁状态标志(线程使用到),线程持有的锁、偏向线程...
  • 2、对象头里包括:运行时元数据、类型指针、实例数据、对齐填充 ① 运行时元数据里又包括:哈希值(HashCode)、GC分代年龄、锁状态标志 哈希值:它是一个地址,用于栈对堆空间中对象的引用指向,不然栈是无法找到堆...
  • 1. 对象头 2. 实例数据 3. 对齐填充 事实上实例数据部分存储的就是我们在对象中定义的实例成员变量包括从父类中继承过来的(不包括类成员,它们在方法区中分配),实例成员变量包括基本数据类型和引用数据类型,...
  • 有那么一段时间,“对象”基本上是当时IT届最流行的词语,无论什么东西都要搭上“对象”的概念才够体面。NT核就诞生在那个年代,所以在其设计概念中有“内核对象”这么一个牛逼的物件。几乎所有的windows内核组件,...
  • 今天在网上冲浪,马上被这个神秘的面试题所吸引,Object o = new Object()占多少内存?第一眼看到就觉得...Header就是我们常说的对象头 对象头又分为三个部分MarkWord、Klass、ArrayLength MarkWord 用于存放的
  • 返回用户代理的字符串表示(就是包括浏览器版本信息等的字符串) 语法 navigator.userAgent 几种浏览的user_agent.,像360的兼容模式用的是IE、极速模式用的是chrom的内核。 使用userAgent判断使用的是什么...
  • 大家好,我来了,本期为大家带来的前端开发知识是”Web前端:Jsp九大内置对象分别是什么?“,有兴趣做前端的朋友,一起来看看吧!...(包括头信息、系统信息、请求方式以及请求参数等)。request对象的...
  • 在计算机中,文件是不可缺少的部分,是指具有文件名的若干相关元素的集合,元素通常是记录,记录又是一组有意义的数据...基本数据项是用于描述一个对象的某种属性的字符集,是数据组织中可以命名的最小逻辑数据单位...
  • 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding) 注:下面的都是在HotSpot中的实现 对象头包括两部分信息,Mark Word和类型指针...
  • 一个Java对象在内存中包括3个部分:对象头、实例数据和对齐填充 1.1 对象头 Mark Word 状态标识。与虚拟机位数一样,一般64bit,32bit很少。下图是一个32位虚拟机的Mark Word示例: 从对象头中可以获取到两点信息...
  • 内置对象requestrequest 对象是 ...(包括头信息、系统信息、请求方式以及请求参数等)。request对象的作用域为一次请求。responseresponse 代表的是对客户端的响应,主要是将JSP容器处理过的对象传回到客户端。resp...
  • 对象创建过程,new发生了什么 1.对象创建过程: ...内存分配完成后,JVM将分配到的内存空间初始化为零值(不包括对象头),如果使用TLAB,这个过程也可以在TLAB(并发条件下如何保证线程安全)分配时进行:这一步操
  • Java对象的内存布局

    千次阅读 2020-06-19 11:20:31
    首先我们都知道,堆中存储的对象包括普通对象和数组对象,而每个对象在内存中都由三个部分组成,分别为对象头、实例数据和补齐部分。 其中,普通对象的对象头中有markword和classPointer两个部分,而数组对象比普通...
  • JVM之对象总结

    2020-05-17 16:02:24
    对象头具体包括什么?对象怎么定位?对象怎么分配?Object o = new Object();在内存中占用多少字节? 对象的创建过程? 1.class loading 把class文件加载到内存 2.class linking(verification验证,preparation准备...
  • 对象的创建过程

    2021-02-22 10:44:30
    4、对象头具体包括什么 5、对象怎么定位 6、对象怎么分配 7、Object o=new Object()在内存中占用多少个字节 对象的创建过程 源码 class T{ int m=8; } T t=new T(); 汇编码(字节码文件中的信息) 0 new #2...
  • 背景 对象的创建过程? DCL与volatile问题? 对象在内存中的存储布局?...对象头具体包括什么? 对象怎么定位? 对象怎么分配? Object o = new Object(),在内存中占用多少字节? 过程 对象的创建过程 小结 ...
  • HTTP协议的请求对象和响应对象

    千次阅读 2018-07-24 16:08:38
    ... 什么是HTTP,Http是超文本...请求对象分为请求,请求行以及请求实体下面分别来讲一下:  请求行包括:传输方式(get或post) 请求的地址(url) 协议的版本  请求中只有:只有键值对形式存在的参数  ...
  • 文章目录对象的内存布局请解释一下对象的创建过程对象在内存中的存储布局一个对象多少字节【16个字节】对象头具体包括什么markword 64 位IdentityHashCode对象定位 对象的内存布局 请解释一下对象的创建过程 类加载...
  • 目录Java对象存储:(HOTSPOT虚拟机)什么是对象头,具体包括什么Mark Word分析 (64位):Class Pointer (类型指针)array length(数组特有)实例数据(Instance)对其填充(padding)如何获取的元数据通过句柄访问对象(间接)...
  • [转] 完整的教育包括什么

    千次阅读 2005-08-20 00:56:00
    大多时间在菜田间、家里、集三点一线过来的。 可如今,姑父姑母的操劳并没有停止,说是为了给表弟读书,还欠下3万多块钱。我问,那大表弟已经工作7年多了,怎么还会有这么多债?姑母说,他工作第二年,刚攒了点...
  • JVM_底层部分面试题

    2020-10-09 08:45:02
    (单例模式,指令重排)对象在内存中的存储布局(对象和数组的存储不同)对象头包括什么?(Markword,class pointer)对象怎么定位?(直接、间接)对象怎么分配?(栈上-线程本地-Edum-Old)Object o = new Object...
  • JVM底层部分面试题

    2020-06-21 22:40:44
    (单例模式,指令重排)对象在内存中的存储布局(对象和数组的存储不同)对象头包括什么?(Markword,class pointer)对象怎么定位?(直接、间接)对象怎么分配?(栈上-线程本地-Edum-Old)Object o = new Object...
  • JVM调优基础篇-java对象大小计算

    多人点赞 2020-05-17 15:28:03
    一个Java对象在内存中包括对象头、实例数据和补齐填充3个部分 由于本文主要是讲述对象的大小计算,所以不会详细讲解每个部分的作用,有兴趣可以上网搜索一些相关文章阅读。 对象头 所有对象都会有的部分: Mark ...
  • 3.对象头具体包括什么? 4.对象怎么定位? 1.解释一下对象的创建过程? T t = new T(); 首先创建对象的时候,会先检查对象的class类有没有加载过,如果没加载过就执行类加载过程 class loading(加载) 通过一个类...

空空如也

空空如也

1 2 3 4 5 ... 12
收藏数 237
精华内容 94
关键字:

对象头包括什么