百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

Java 对象头那点事 java 对象头 monitor

suiw9 2024-11-04 15:23 23 浏览 0 评论

概览


  • 对象头
    存放:关于堆对象的布局、类型、GC状态、同步状态和标识哈希码的基本信息。Java对象和vm内部对象都有一个共同的对象头格式。
    (后面做详细介绍)
  • 实例数据
    存放:类的数据信息,父类的信息,对象字段属性信息。
    如果对象有属性字段,则这里会有数据信息。如果对象无属性字段,则这里就不会有数据。
    根据字段类型的不同占不同的字节,例如boolean类型占1个字节,int类型占4个字节等等;
  • 对齐填充
    存放:为了字节对齐,填充的数据,不是必须的。
    默认情况下,Java虚拟机堆中对象的起始地址需要对齐至8的倍数。
    假如对象头大小为12,实例数据大小为5,最近且大于12+5的8的倍数值是24,则对齐补充大小为:24-12-5=7。

为什么需要对象填充?

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

对象头

mark word

OpenJDK(JDK8)地址:https://github.com/openjdk/jdk
根据OpenJDK 官方源码中MarkOop.hpp文件中给的注释介绍,可以大概看出mark word的组成。

MarkOop.hpp中的注释1:

32 bits:
--------
           hash:25 ------------>| age:4    biased_lock:1 lock:2 (normal object)
           JavaThread*:23 epoch:2 age:4    biased_lock:1 lock:2 (biased object)
           size:32 ------------------------------------------>| (CMS free block)
           PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)

64 bits:
--------
           unused:25 hash:31 -->| unused:1   age:4    biased_lock:1 lock:2 (normal object)
           JavaThread*:54 epoch:2 unused:1   age:4    biased_lock:1 lock:2 (biased object)
           PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)
           size:64 ----------------------------------------------------->| (CMS free block)

MarkOop.hpp中的注释2:

    [JavaThread* | epoch | age | 1 | 01]       lock is biased toward given thread
    [0           | epoch | age | 1 | 01]       lock is anonymously biased

  - the two lock bits are used to describe three states: locked/unlocked and monitor.

    [ptr             | 00]  locked             ptr points to real header on stack
    [header      | 0 | 01]  unlocked           regular object header
    [ptr             | 10]  monitor            inflated lock (header is wapped out)
    [ptr             | 11]  marked             used by markSweep to mark an object
                                               not valid at any other time

MarkOop.hpp中的源码1:

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

如图:


MarkOop.hpp中的源码2:

  enum { locked_value             = 0,
         unlocked_value           = 1,
         monitor_value            = 2,
         marked_value             = 3,
         biased_lock_pattern      = 5
  };
  • locked_value
    轻量级锁状态值,mark word 最后2位为00,转为10进制为0。
  • unlocked_value
    无锁状态值,mark word 最后3位为001,转为10进制为1。
  • monitor_value
    重量级锁状态值,mark word 最后2位为10,转为10进制为2。
  • marked_value
    mark word 最后2位为11,转为10进制为3。
    作用比较复杂,
    1:当锁升级为重量级锁的过程中,会将markword设置为这个值。
    2:当对象GC时也要使用这个值。

markOop.hpp部分源码如下:

  // 仅用于存储到Lock Record中,用来表示锁正在使用重量级监视器(轻量级锁膨胀为重量级锁之前会这么做)
  static markOop unused_mark() {
    return (markOop) marked_value;
  }

  // age operations
  markOop set_marked()   { return markOop((value() & ~lock_mask_in_place) | marked_value); }
  markOop set_unmarked() { return markOop((value() & ~lock_mask_in_place) | unlocked_value); }
  • biased_lock_pattern
    偏向锁状态值,mark word 最后3位为101,转为10进制为5。

markOop.cpp中还有以下代码,用以判断当前markword处于哪种锁状态:

  // 轻量级锁
  bool is_locked()   const {
    return (mask_bits(value(), lock_mask_in_place) != unlocked_value);
  }
  // 偏向锁
  bool is_unlocked() const {
    return (mask_bits(value(), biased_lock_mask_in_place) == unlocked_value);
  }
  // marked
  bool is_marked()   const {
    return (mask_bits(value(), lock_mask_in_place) == marked_value);
  }
  // 无锁
  bool is_neutral()  const { return (mask_bits(value(), biased_lock_mask_in_place) == unlocked_value); }
  // 膨胀时 markOop 的特殊临时状态。 在锁外查看标记的代码需要考虑到这一点。
  bool is_being_inflated() const { return (value() == 0); }
  // 锁对象处于升级为重量级锁的过程中
  static markOop INFLATING() { return (markOop) 0; }

为什么对象头分代占4bit
因为对象经过15次GC就会被放入老年代,而15转化为二进制就是1111,干好占4bit.


epoch的作用
抄自于:http://www.itqiankun.com/article/bias-lock-epoch-effect

其本质是一个时间戳,代表了偏向锁的有效性,epoch存储在可偏向对象的MarkWord中。

①:除了对象中的epoch,对象所属的类class信息中,也会保存一个epoch值。

②:每当遇到一个全局安全点时(这里的意思是说批量重偏向没有完全替代了全局安全点,全局安全点是一直存在的),比如要对class C 进行批量再偏向,则首先对 class C中保存的epoch进行增加操作,得到一个新的epoch_new。

③:然后扫描所有持有 class C 实例的线程栈,根据线程栈的信息判断出该线程是否锁定了该对象,仅将epoch_new的值赋给被锁定的对象中,也就是现在偏向锁还在被使用的对象才会被赋值epoch_new。

④:退出安全点后,当有线程需要尝试获取偏向锁时,直接检查 class C 中存储的 epoch 值是否与目标对象中存储的 epoch 值相等, 如果不相等,则说明该对象的偏向锁已经无效了(因为(3)步骤里面已经说了只有偏向锁还在被使用的对象才会有epoch_new,这里不相等的原因是class C里面的epoch值是epoch_new,而当前对象的epoch里面的值还是epoch),此时竞争线程可以尝试对此对象重新进行偏向操作。

klass point

元数据指针class pointer,即指向方法区的instanceKlass实例(虚拟机通过这个指针来群定这个对象是哪个类的实例)。

oop.hpp中的源码:

class oopDesc {
  friend class VMStructs;
 private:
  volatile markOop  _mark;
  union _metadata {
    Klass*      _klass;
    narrowKlass _compressed_klass;
  } _metadata;

length field

该属性只有数组对象才有,用以表示数组的长度。

arrayOop.hpp中有这么一段注释:

// The layout of array Oops is:
//
//  markOop
//  Klass*    // 32 bits if compressed but declared 64 in LP64.
//  length    // shares klass memory or allocated after declared fields.

总结

可能面试的时候会被问到这个问题:为什么一个对象可以当成一把锁?
这方面可以与上文中提到的对象头、markword 进行回答即可。

文章来自https://www.cnblogs.com/zgq7/p/16250149.html

相关推荐

俄罗斯的 HTTPS 也要被废了?(俄罗斯网站关闭)

发布该推文的ScottHelme是一名黑客,SecurityHeaders和ReportUri的创始人、Pluralsight作者、BBC常驻黑客。他表示,CAs现在似乎正在停止为俄罗斯域名颁发...

如何强制所有流量使用 HTTPS一网上用户

如何强制所有流量使用HTTPS一网上用户使用.htaccess强制流量到https的最常见方法可能是使用.htaccess重定向请求。.htaccess是一个简单的文本文件,简称为“.h...

https和http的区别(https和http有何区别)

“HTTPS和HTTP都是数据传输的应用层协议,区别在于HTTPS比HTTP安全”。区别在哪里,我们接着往下看:...

快码住!带你十分钟搞懂HTTP与HTTPS协议及请求的区别

什么是协议?网络协议是计算机之间为了实现网络通信从而达成的一种“约定”或“规则”,正是因为这个“规则”的存在,不同厂商的生产设备、及不同操作系统组成的计算机之间,才可以实现通信。简单来说,计算机与网络...

简述HTTPS工作原理(简述https原理,以及与http的区别)

https是在http协议的基础上加了一层SSL(由网景公司开发),加密由ssl实现,它的目的是为用户提供对网站服务器的身份认证(需要CA),以至于保护交换数据的隐私和完整性,原理如图示。1、客户端发...

21、HTTPS 有几次握手和挥手?HTTPS 的原理什么是(高薪 常问)

HTTPS是3次握手和4次挥手,和HTTP是一样的。HTTPS的原理...

一次安全可靠的通信——HTTPS原理

为什么HTTPS协议就比HTTP安全呢?一次安全可靠的通信应该包含什么东西呢,这篇文章我会尝试讲清楚这些细节。Alice与Bob的通信...

为什么有的网站没有使用https(为什么有的网站点不开)

有的网站没有使用HTTPS的原因可能涉及多个方面,以下是.com、.top域名的一些见解:服务器性能限制:HTTPS使用公钥加密和私钥解密技术,这要求服务器具备足够的计算能力来处理加解密操作。如果服务...

HTTPS是什么?加密原理和证书。SSL/TLS握手过程

秘钥的产生过程非对称加密...

图解HTTPS「转」(图解http 完整版 彩色版 pdf)

我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取。所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。...

HTTP 和 HTTPS 有何不同?一文带你全面了解

随着互联网时代的高速发展,Web服务器和客户端之间的安全通信需求也越来越高。HTTP和HTTPS是两种广泛使用的Web通信协议。本文将介绍HTTP和HTTPS的区别,并探讨为什么HTTPS已成为We...

HTTP与HTTPS的区别,详细介绍(http与https有什么区别)

HTTP与HTTPS介绍超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的...

一文让你轻松掌握 HTTPS(https详解)

一文让你轻松掌握HTTPS原文作者:UC国际研发泽原写在最前:欢迎你来到“UC国际技术”公众号,我们将为大家提供与客户端、服务端、算法、测试、数据、前端等相关的高质量技术文章,不限于原创与翻译。...

如何在Spring Boot应用程序上启用HTTPS?

HTTPS是HTTP的安全版本,旨在提供传输层安全性(TLS)[安全套接字层(SSL)的后继产品],这是地址栏中的挂锁图标,用于在Web服务器和浏览器之间建立加密连接。HTTPS加密每个数据包以安全方...

一文彻底搞明白Http以及Https(http0)

早期以信息发布为主的Web1.0时代,HTTP已可以满足绝大部分需要。证书费用、服务器的计算资源都比较昂贵,作为HTTP安全扩展的HTTPS,通常只应用在登录、交易等少数环境中。但随着越来越多的重要...

取消回复欢迎 发表评论: