hashcode java_java 的Object类的hashcode()方法具体是怎么实现的?

轻松解说Object.hashcode()的实现,让你看着不累!

intptr_t ObjectSynchronizer::FastHashCode (Thread * Self, oop obj) {

// 如果启用偏向锁

if (UseBiasedLocking) {

// NOTE: many places throughout the JVM do not expect a safepoint

// to be taken here, in particular most operations on perm gen

// objects. However, we only ever bias Java instances and all of

// the call sites of identity_hash that might revoke biases have

// been checked to make sure they can handle a safepoint. The

// added check of the bias pattern is to avoid useless calls to

// thread-local storage.

// 如果对象处于“已偏向”状态

if (obj->mark()->has_bias_pattern()) {

// Box and unbox the raw reference just in case we cause a STW safepoint.

// 将obj对象包装成一个句柄->hobj

Handle hobj (Self, obj) ;

// Relaxing assertion for bug 6320749.

// 保证程序的执行条件

assert (Universe::verify_in_progress() ||

!SafepointSynchronize::is_at_safepoint(),

"biases should not be seen by VM thread here");

// 撤销偏向锁

BiasedLocking::revoke_and_rebias(hobj, false, JavaThread::current());

// 这里根据Handle类定义的无参函数对象,将obj再取出来

obj = hobj() ;

// 看看是不是确保成功撤销了

assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");

}

}

// hashCode() is a heap mutator ...

// Relaxing assertion for bug 6320749.

/**

* 1. 确保当前的执行路径不处在全局安全点上;

* 2. 确保当前线程是个JavaThread

* 3. 确保当前线程没有被block

*/

assert (Universe::verify_in_progress() ||

!SafepointSynchronize::is_at_safepoint(), "invariant") ;

assert (Universe::verify_in_progress() ||

Self->is_Java_thread() , "invariant") ;

assert (Universe::verify_in_progress() ||

((JavaThread *)Self)->thread_state() != _thread_blocked, "invariant") ;

ObjectMonitor* monitor = NULL;

markOop temp, test;

intptr_t hash;

// 读出一个稳定的mark,防止obj正处于锁膨胀状态,如果正在膨胀,就等它膨胀完,再读出来

markOop mark = ReadStableMark (obj);

// object should remain ineligible for biased locking

// 我擦,你不会还处于“已偏向”状态吧

assert (!mark->has_bias_pattern(), "invariant") ;

// 如果mark现在处于中立状态了->unlock 这时候mark的结构应该是 [hash|age|0|01]

if (mark->is_neutral()) {

// 看看mark中是不是有一个存在的hash值

hash = mark->hash(); // this is a normal header

// 我靠,有了,省事了,直接返回吧

if (hash) { // if it has hash, just return it

return hash;

}

// 没有,那我就根据hashCode的算法规则重新算一个出来吧

hash = get_next_hash(Self, obj); // allocate a new hash code

// 把上面的hash结果merge到mark中去,看到我写的那个结构了吗,放到hash那个位置

// 得到一个临时的temp,为什么这么干,继续看下面

temp = mark->copy_set_hash(hash); // merge the hash code into header

// use (machine word version) atomic operation to install the hash

// 上面的E文注释写得已经很直白了,CAS安装hash值咯

test = (markOop) Atomic::cmpxchg_ptr(temp, obj->mark_addr(), mark);

if (test == mark) {

// 看来CAS操作成功了,返回hash

return hash;

}

// If atomic operation failed, we must inflate the header

// into heavy weight monitor. We could add more code here

// for fast path, but it does not worth the complexity.

// 妈的,CAS失败了,上面E文说了,我们要把对象头膨胀成重量级锁了!

// 看看重锁状态时,mark的结构吧- monitor_ptr|10

// Anyway, 看看现在你是不是已经是重锁状态了吧

} else if (mark->has_monitor()) {

// 好家伙,你已经膨胀成重锁了嘛

monitor = mark->monitor();

// 那么我们就从ObjectMonitor对象中将mark取出来看看吧

temp = monitor->header();

// 这时候mark应该是无锁中立状态了,结构看上面吧!

assert (temp->is_neutral(), "invariant") ;

// 完事OK,取出来返回吧!

hash = temp->hash();

if (hash) {

return hash;

}

// Skip to the following code to reduce code size

// 锁对象正处在轻量级锁的状态,并且锁的持有者还是当前线程呢!

} else if (Self->is_lock_owned((address)mark->locker())) {

// 直接从线程栈里把mark取出来吧

temp = mark->displaced_mark_helper(); // this is a lightweight monitor owned

// mark不是中立状态?你搞笑吧!

assert (temp->is_neutral(), "invariant") ;

// 取出来返回咯

hash = temp->hash(); // by current thread, check if the displaced

if (hash) { // header contains hash code

return hash;

}

// WARNING:

// The displaced header is strictly immutable.

// It can NOT be changed in ANY cases. So we have

// to inflate the header into heavyweight monitor

// even the current thread owns the lock. The reason

// is the BasicLock (stack slot) will be asynchronously

// read by other threads during the inflate() function.

// Any change to stack may not propagate to other threads

// correctly.

}

// 苦逼地等待你膨胀成重锁了...

// Inflate the monitor to set hash code

monitor = ObjectSynchronizer::inflate(Self, obj);

// Load displaced header and check it has hash code

// 从重锁对象中load出对象头mark来,看看是否已经有了一个hash值了

mark = monitor->header();

// check 不解释了

assert (mark->is_neutral(), "invariant") ;

hash = mark->hash();

// hash值还是空的,well,我们还是算一个出来吧!

// 下面的逻辑跟上面的一段一致,哥就不用费口舌了...

if (hash == 0) {

hash = get_next_hash(Self, obj);

temp = mark->copy_set_hash(hash); // merge hash code into header

assert (temp->is_neutral(), "invariant") ;

test = (markOop) Atomic::cmpxchg_ptr(temp, monitor, mark);

if (test != mark) {

// The only update to the header in the monitor (outside GC)

// is install the hash code. If someone add new usage of

// displaced header, please update this code

hash = test->hash();

assert (test->is_neutral(), "invariant") ;

assert (hash != 0, "Trivial unexpected object/monitor header usage.");

}

}

// We finally get the hash

// 费了好大劲,终于拿到hash值了,鸡冻~

return hash;

}

上面还有一个重要的函数get_next_hash, hachCode是hash的生成策略,默认值是5,可在虚拟机启动时配置(由于算法比较严肃,轻松不了了~~):

// hashCode() generation :

//

// Possibilities:

// * MD5Digest of {obj,stwRandom}

// * CRC32 of {obj,stwRandom} or any linear-feedback shift register function.

// * A DES- or AES-style SBox[] mechanism

// * One of the Phi-based schemes, such as:

// 2654435761 = 2^32 * Phi (golden ratio)

// HashCodeValue = ((uintptr_t(obj) >> 3) * 2654435761) ^ GVars.stwRandom ;

// * A variation of Marsaglia's shift-xor RNG scheme.

// * (obj ^ stwRandom) is appealing, but can result

// in undesirable regularity in the hashCode values of adjacent objects

// (objects allocated back-to-back, in particular). This could potentially

// result in hashtable collisions and reduced hashtable efficiency.

// There are simple ways to "diffuse" the middle address bits over the

// generated hashCode values:

//

static inline intptr_t get_next_hash(Thread * Self, oop obj) {

intptr_t value = 0 ;

if (hashCode == 0) {

// This form uses an unguarded global Park-Miller RNG,

// so it's possible for two threads to race and generate the same RNG.

// On MP system we'll have lots of RW access to a global, so the

// mechanism induces lots of coherency traffic.

value = os::random() ;

} else

if (hashCode == 1) {

// This variation has the property of being stable (idempotent)

// between STW operations. This can be useful in some of the 1-0

// synchronization schemes.

intptr_t addrBits = cast_from_oop(obj) >> 3 ;

value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ;

} else

if (hashCode == 2) {

value = 1 ; // for sensitivity testing

} else

if (hashCode == 3) {

value = ++GVars.hcSequence ;

} else

if (hashCode == 4) {

value = cast_from_oop(obj) ;

} else {

// Marsaglia's xor-shift scheme with thread-specific state

// This is probably the best overall implementation -- we'll

// likely make this the default in future releases.

unsigned t = Self->_hashStateX ;

t ^= (t << 11) ;

Self->_hashStateX = Self->_hashStateY ;

Self->_hashStateY = Self->_hashStateZ ;

Self->_hashStateZ = Self->_hashStateW ;

unsigned v = Self->_hashStateW ;

v = (v ^ (v >> 19)) ^ (t ^ (t >> 8)) ;

Self->_hashStateW = v ;

value = v ;

}

value &= markOopDesc::hash_mask;

if (value == 0) value = 0xBAD ;

assert (value != markOopDesc::no_hash, "invariant") ;

TEVENT (hashCode: GENERATE) ;

return value;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/398122.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 数据库升级解决方案

转自&#xff1a;http://blog.csdn.net/leehong2005/article/details/9128501 请考虑如下情况&#xff1a; 在数据库升级时&#xff0c;不同版本的数据库&#xff0c;他们定义的表结构完全可能是不一样的&#xff0c;比如V1.0的表A有10个column&#xff0c;而在V1.1的表A有12个…

区间素数筛法

给定整数a和b&#xff0c;请问区间[a,b)内有多少个素数&#xff1f; a<b<10^12 b-a<10^6 因为b以内合数的最小质因数一定不超过sqrt(b),如果有sqrt(b)以内的素数表的话&#xff0c;就可以把筛选法用在[a,b)上了,先分别做好[2,sqrt(b))的表和[a,b)的表&#xff0c;然后…

[php入门] 3、WAMP中的集成MySQL相关基础操作

前言&#xff1a;本文以小白视角了解WAMP集成开发环境中的MYSQL&#xff0c;涉及的面广而浅&#xff0c;算是导读性质。 1、启动运行熟悉WAMP中的MySQL 先有库、再有表、数据最终以记录的形式插入表中。其中对数据进行操作使用SQL语句&#xff0c;SQL是结构化的查询语言。 在wa…

apns java 证书_APNS推送服务证书制作 图文详解教程(新)

iOS消息推送的工作机制可以简单的用下图来概括&#xff1a;Provider是指某个iPhone软件的Push服务器&#xff0c;APNS是Apple Push Notification Service的缩写&#xff0c;是苹果的服务器。上图可以分为三个阶段&#xff1a;第一阶段&#xff1a;应用程序把要发送的消息、目的…

java 凑整_Java语言中的取整运算(包括截尾取整,四舍五入,凑整)? – 日记

import java.math.BigDecimal;import java.text.DecimalFormat;public class TestGetInt{public static void main(String[] args){double i2, j2.1, k2.5, m2.9;System.out.println(”舍掉小数取整:Math.floor(2)” (int)Math.floor(i));System.out.println(”舍掉小数取整:M…

企业员工工资管理系统

企业工资管理是人力资源管理的一个核心环节,在市场经济和全球一体化的大背景下&#xff0c;随着人力资源管理在战略层面上发挥着越来越重要的作用&#xff0c;传统的薪酬制度已于现代化的要求不匹配&#xff0c;并越来越限制着企业的发展。本系统以员工的考勤信息作为基础&…

Android近场通信---NFC基础(二)(转)

转自 http://blog.csdn.net/think_soft/article/details/8171256 应用程序如何调度NFC标签 当标签调度系统完成对NFC标签和它的标识信息封装的Intent对象的创建时&#xff0c;它会把该Intent对象发送给感兴趣的应用程序。如果有多个应用程序能够处理该Intent对象&#xff0c;就…

:base(参数)

:base(必须有值)&#xff1a;作用是将父类的值继承过来&#xff0c;如果不在构造函数中加入&#xff1a;base(变量) 的话&#xff0c;原父类中的 Model则无法继承过来。 例如&#xff1a;在父类MSG_Model,有连个属性&#xff0c;如图 1.子类构造函数不写:base(参数) 2.1.子类构…

如何在{{input}}中使用action

文章来源&#xff1a;Ember Teach 开发中经常遇到需要在一个input输入框触发JS函数&#xff0c;那么对于Ember.js的{{input}}又如何才能出发自定义的action呢&#xff1f; 实现起来非常简单&#xff01;请看下面的代码演示&#xff1a; 旧版本实现方式 {{input type"text&…

java json utf-8_Java 编码 和JSON

1.编码序列化(urlencode编码)&#xff1a;经过urlencode编码String a"[{\"clubNo\":\"10000002\",\"clubType\":\"1\"},{\"clubNo\":\"10000003\",\"clubType\":\"4\"},{\"clubNo\…

MVC5 + EF6 完整入门教程三

MVC5 EF6 完整入门教程三 原文:MVC5 EF6 完整入门教程三期待已久的EF终于来了。 学完本篇文章&#xff0c;你将会掌握基于EF数据模型的完整开发流程。 本次将会完成EF数据模型的搭建和使用。 基于这个模型&#xff0c;将之前的示例添加数据库查询验证功能。 文章提纲 概…

纯手写的css3正方体旋转效果

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>css3旋转立方体效果</title><style type"text/css">*{margin: 0;padding: 0;}.box{width: 400px;height: 400px;border: 1px solid #000;margin: 30p…

Expect 教程中文版

http://blog.csdn.net/chinalinuxzend/article/details/1842588原贴&#xff1a;http://blog.chinaunix.net/u/13329/showart.php?id110100 Expect 教程中文版[From] http://www.linuxeden.com/edu/doctext.php?docid799  本教程由*葫芦娃*翻译&#xff0c;并做…

java boolean转int,java如何将int转换为boolean

When i convert:int B1;boolean AB;It gives error: Incompatible types, which is trueBut when I write this code:int C0;boolean AC1;it gives falsewhile if I change value of C to 1 it gives true.I dont understand how compiler is doing it.解决方案int C0;boolean …

习惯看新闻头条 一个程序员分享的工作心得

原本想找链接的。可是...我还是选择手打 原作者&#xff1a;刘鹏看未来 原文标题 10程序员总结的20条经验教训 开发 1.从小事做起&#xff0c;然后再扩展 无论是创建一个新的系统&#xff0c;还是添加功能到现有的系统中&#xff0c;我总是从一个简单到几乎任何所需功能的版…

Java-JUC(十):线程按序交替执行

问题&#xff1a; 有a、b、c三个线程&#xff0c;使得它们按照abc依次执行10次。 实现&#xff1a; package com.dx.juc.test;import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;public…

IntelliTrace 调试、定位异常

最近看了一个开源数据库管理&#xff0c;然后没有认真看它的配置环境&#xff0c;想看看是什么东西&#xff0c; 然后发现有类型转换的错误&#xff0c;但是一下子也定位不到哪里出错&#xff1f; 所以对于这种一下子找不到异常在哪里的&#xff0c;可以使用intellitrace智能跟…

java referencemap_Java中TypeReference用法说明

来源于&#xff1a;https://blog.csdn.net/zhuzj12345/article/details/102914545在使用fastJson时,对于泛型的反序列化很多场景下都会使用到TypeReference&#xff0c;例如&#xff1a;void testTypeReference() {List list new ArrayList<>();list.add(1);list.add(9)…

zedboard--zynq使用自带外设IP让ARM PS访问FPGA(八) 转载

文章来源 http://blog.chinaaet.com/detail/34609 熟悉了xps的操作&#xff0c;IP添加&#xff0c;总线连接设置&#xff0c;图形化方法检查&#xff08;open graphical design view&#xff09;&#xff0c;检查总线及端口连接。 在file下面的图标中&#xff0c;打开导出到SDK…

[php入门] 4、HTML基础入门一篇概览

[php入门] 1、从安装开发环境环境到&#xff08;庄B&#xff09;做个炫酷的登陆应用 [php入门] 2、基础核心语法大纲 [php入门] 3、WAMP中的集成MySQL相关基础操作 1、HTML的作用   HTML是超文本标记语言&#xff0c;主要用于制作页面结构&#xff1b;而经常与之一起用的CSS是…