深入理解多线程(三)—— Java的对象头

上一篇文章中我们从HotSpot的源码入手,介绍了Java的对象模型。这一篇文章在上一篇文章的基础上再来介绍一下Java的对象头。主要介绍一下对象头的作用,结构以及他和锁的关系。

十多年的陇西网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。成都营销网站建设的优势是能够根据用户设备显示端的尺寸不同,自动调整陇西建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。创新互联从事“陇西网站设计”,“陇西网站推广”以来,每个客户项目都认真落实执行。

Java对象模型回顾与勘误

在上一篇文章中,关于对象头的部分描述有误,我已经在我博客的文章中就行修正 。这里再重新表述一下。

每一个Java类,在被JVM加载的时候,JVM会给这个类创建一个instanceKlass,保存在方法区,用来在JVM层表示该Java类。当我们在Java代码中,使用new创建一个对象的时候,JVM会创建一个instanceOopDesc对象,这个对象中包含了对象头以及实例数据。

这里提到的对象头到底是什么呢?

 
 
 
 
  1. class oopDesc { 
  2.   friend class VMStructs; 
  3.  private: 
  4.   volatile markOop  _mark; 
  5.   union _metadata { 
  6.     wideKlassOop    _klass; 
  7.     narrowOop       _compressed_klass; 
  8.   } _metadata; 

上面代码中的_mark和_metadata其实就是对象头的定义。关于_metadata之前就介绍过,这里不再赘述。由于这个专题主要想介绍和JAVA并发相关的知识,所以本文展开介绍一下_mark ,即mark word。

对象头信息是与对象自身定义的数据无关的额外存储成本,考虑到虚拟机的空间效率,Mark Word被设计成一个非固定的数据结构以便在极小的空间内存储尽量多的信息,它会根据对象的状态复用自己的存储空间。

对markword的设计方式上,非常像网络协议报文头:将mark word划分为多个比特位区间,并在不同的对象状态下赋予比特位不同的含义。下图描述了在32位虚拟机上,在对象不同状态时 mark word各个比特位区间的含义。

同样,在HotSpot的源码中我们可以找到关于对象头对象的定义,会一一印证上图的描述。对应与markOop.hpp类。

 
 
 
 
  1. enum { age_bits                 = 4, 
  2.       lock_bits                = 2, 
  3.       biased_lock_bits         = 1, 
  4.       max_hash_bits            = BitsPerWord - age_bits - lock_bits - biased_lock_bits, 
  5.       hash_bits                = max_hash_bits > 31 ? 31 : max_hash_bits, 
  6.       cms_bits                 = LP64_ONLY(1) NOT_LP64(0), 
  7.       epoch_bits               = 2 
  8. }; 

从上面的枚举定义中可以看出,对象头中主要包含了GC分代年龄、锁状态标记、哈希码、epoch等信息。

从上图中可以看出,对象的状态一共有五种,分别是无锁态、轻量级锁、重量级锁、GC标记和偏向锁。在32位的虚拟机中有两个Bits是用来存储锁的标记为的,但是我们都知道,两个bits最多只能表示四种状态:00、01、10、11,那么第五种状态如何表示呢 ,就要额外依赖1Bit的空间,使用0和1来区分。

在32位的HotSpot虚拟机 中对象未被锁定的状态下,Mark Word的32个Bits空间中的25Bits用于存储对象哈希码(HashCode),4Bits用于存储对象分代年龄,2Bits用于存储锁标志位,1Bit固定为0,表示非偏向锁。

markOop.hpp类中有关于对象状态的定义:

 
 
 
 
  1. enum { locked_value             = 0, 
  2.          unlocked_value           = 1, 
  3.          monitor_value            = 2, 
  4.          marked_value             = 3, 
  5.          biased_lock_pattern      = 5 
  6.   }; 

简单翻译一下:

 
 
 
 
  1. locked_value(00) = 0  
  2. unlocked_value(01) = 1  
  3. monitor_value(10) = 2  
  4. marked_value(11) = 3  
  5. biasedlockpattern(101) = 5 

关于为什么要定义这么多状态,上面提到的轻量级锁、重量级锁、偏向锁以及他们之前的关系,会在下一篇文章中重点阐述。

【本文是专栏作者Hollis的原创文章,作者微信公众号Hollis(ID:hollischuang)】

戳这里,看该作者更多好文

名称栏目:深入理解多线程(三)—— Java的对象头
转载源于:http://www.shufengxianlan.com/qtweb/news22/243622.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联