我的编程空间,编程开发者的网络收藏夹
学习永远不晚

java Object的hashCode方法怎么使用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

java Object的hashCode方法怎么使用

这篇文章主要讲解了“java Object的hashCode方法怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java Object的hashCode方法怎么使用”吧!

    1. 背景介绍

    在为重写hashCode方法的时候,看到hashCode打印出的数据像是一个地址值,很是好奇。

    加之最近在研读jvm源码,特此一探究竟,看看在hotspot中hashCode究竟是如何实现的。

    2. 调用过程梳理

    java的Object代码

    public native int hashCode();

    通过官产jdk的Object.class的源码, 发现hashCode被native修饰. 因此这个方法应该是在jvm中通过c/c++实现

    jvm的hashCode相关代码

    首先观察Object.java对应的Object.c代码

    // 文件路径: jdk\class="lazy" data-src\share\native\java\lang\Object.cstatic JNINativeMethod methods[] = {    {"hashCode",    "()I",                    (void *)&JVM_IHashCode}, // 这个方法就是我们想看的hashCode方法    {"wait",        "(J)V",                   (void *)&JVM_MonitorWait},    {"notify",      "()V",                    (void *)&JVM_MonitorNotify},    {"notifyAll",   "()V",                    (void *)&JVM_MonitorNotifyAll},    {"clone",       "()Ljava/lang/Object;",   (void *)&JVM_Clone},};

    进一步进入到jvm.h文件中, 这个文件中包含了很多java调用native方法的接口

    // hotspot\class="lazy" data-src\share\vm\prims\jvm.hJNIEXPORT jint JNICALLJVM_IHashCode(JNIEnv *env, jobject obj); // 此时定了已hashCode方法的接口, 具体实现在jvm.cpp中
    // hotspot\class="lazy" data-src\share\vm\prims\jvm.cpp// java.lang.Object ///JVM_ENTRY(jint, JVM_IHashCode(JNIEnv* env, jobject handle))  JVMWrapper("JVM_IHashCode");  // as implemented in the classic virtual machine; return 0 if object is NULL  return handle == NULL ? 0 : ObjectSynchronizer::FastHashCode (THREAD, JNIHandles::resolve_non_null(handle)) ; // 如果object为null, 就返回0; 否则就调用ObjectSynchronizer::FastHashCodeJVM_END

    进入到ObjectSynchronizer::FastHashCode

    // hotspot\class="lazy" data-src\share\vm\runtime\synchronizer.cppintptr_t ObjectSynchronizer::FastHashCode (Thread * Self, oop obj) {// .... // 在FastHashCode方法中有一段关键代码: if (mark->is_neutral()) {     hash = mark->hash();              // 首先通过对象的markword中取出hashCode     if (hash) {                       // 如果取调到了, 就直接返回       return hash;     }     hash = get_next_hash(Self, obj);  // 如果markword中没有设置hashCode, 则调用get_next_hash生成hashCode     temp = mark->copy_set_hash(hash); // 生成的hashCode设置到markword中     // use (machine word version) atomic operation to install the hash     test = (markOop) Atomic::cmpxchg_ptr(temp, obj->mark_addr(), mark);     if (test == mark) {       return hash;     } }// ....}

    生成hashCode的方法get_next_hash, 可以支持通过参数配置不同的生成hashCode策略

    // hotspot\class="lazy" data-src\share\vm\runtime\synchronizer.cppstatic inline intptr_t get_next_hash(Thread * Self, oop obj) {  intptr_t value = 0 ;  // 一共支持6中生成hashCode策略, 默认策略值是5  if (hashCode == 0) {  // 策略1: 直接通过随机数生成     value = os::random() ;  } else if (hashCode == 1) {     // 策略2: 通过object地址和随机数运算生成     intptr_t addrBits = cast_from_oop<intptr_t>(obj) >> 3 ;     value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ;  } else if (hashCode == 2) {  // 策略3: 永远返回1, 用于测试     value = 1 ;            // for sensitivity testing  } else if (hashCode == 3) {  // 策略4: 返回一个全局递增的序列数     value = ++GVars.hcSequence ;  } else if (hashCode == 4) {  // 策略5: 直接采用object的地址值     value = cast_from_oop<intptr_t>(obj) ;  } else {     // 策略6: 通过在每个线程中的四个变量: _hashStateX, _hashStateY, _hashStateZ, _hashStateW     // 组合运算出hashCode值, 根据计算结果同步修改这个四个值     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; // 通过hashCode的mask获得最终的hashCode值  if (value == 0) value = 0xBAD ;  assert (value != markOopDesc::no_hash, "invariant") ;  TEVENT (hashCode: GENERATE) ;  return value;}

    3. 关于hashCode值的大小

    前面以及提交到hashCode生成后, 是存储在markword中, 我们在深入看一下这个markword

    // hotspot\class="lazy" data-src\share\vm\oops\markOop.hppclass markOopDesc: public oopDesc { private:  // Conversion  uintptr_t value() const { return (uintptr_t) this; } public:  // Constants  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, // 通过这个定义可知, hashcode可占用31位bit. 在32位jvm中,  hashCode占用25位         cms_bits                 = LP64_ONLY(1) NOT_LP64(0),         epoch_bits               = 2  };  }

    4. 验证

    package test;public class TestHashCode {    public static void main(String[] args) {        Object obj1 = new Object();        Object obj2 = new Object();        System.out.println(obj1.hashCode());        System.out.println(obj2.hashCode());    }}

    通过-XX:hashCode=2这种形式, 可以验证上述的5中hashCode生成策略

    5. 总结

    在64位jvm中, hashCode最大占用31个bit; 32位jvm中, hashCode最大占用25个bit

    hashCode一共有六种生成策略

    序号hashCode策略值描述
    10直接通过随机数生成
    21通过object地址和随机数运算生成
    32永远返回1, 用于测试
    43返回一个全局递增的序列数
    54直接采用object的地址值
    6其他通过在每个线程中的四个变量: _hashStateX, _hashStateY, _hashStateZ, _hashStateW 组合运算出hashCode值, 根据计算结果后修改这个四个值

    默认策略采用策略6, 在globals.hpp文件中定义

      product(intx, hashCode, 5,                                                \          "(Unstable) select hashCode generation algorithm")

    感谢各位的阅读,以上就是“java Object的hashCode方法怎么使用”的内容了,经过本文的学习后,相信大家对java Object的hashCode方法怎么使用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    java Object的hashCode方法怎么使用

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    java Object的hashCode方法怎么使用

    这篇文章主要讲解了“java Object的hashCode方法怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java Object的hashCode方法怎么使用”吧!1. 背景介绍
    2023-06-22

    Java中List.contains(Object object)方法怎么使用

    本篇内容主要讲解“Java中List.contains(Object object)方法怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java中List.contains(Object
    2023-06-29

    Java中hashCode方法怎么用

    这篇文章主要介绍“Java中hashCode方法怎么用”,在日常操作中,相信很多人在Java中hashCode方法怎么用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中hashCode方法怎么用”的疑
    2023-06-29

    Java中Object类的方法怎么用

    这篇文章主要介绍了Java中Object类的方法怎么用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java中Object类的方法怎么用文章都会有所收获,下面我们一起来看看吧。前言:Java的Object 类的
    2023-06-30

    Java中 hashcode方法的作用是什么

    这期内容当中小编将会给大家带来有关Java中 hashcode方法的作用是什么,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Java可以用来干什么Java主要应用于:1. web开发;2. Android
    2023-06-14

    hashcode方法如何在Java项目中使用

    这篇文章给大家介绍hashcode方法如何在Java项目中使用,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率。在Java的Obje
    2023-05-30

    HashSet/TreeSet是怎么使用hashCode()和equal()方法的

    本篇内容主要讲解“HashSet/TreeSet是怎么使用hashCode()和equal()方法的”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“HashSet/TreeSet是怎么使用hash
    2023-06-03

    Java Object类equals方法怎么用

    这篇文章主要介绍“Java Object类equals方法怎么用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java Object类equals方法怎么用”文章能帮助大家解决问题。基本概念:Obj
    2023-06-30

    java中的Object类的toSpring()方法怎么用

    这篇文章主要讲解了“java中的Object类的toSpring()方法怎么用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java中的Object类的toSpring()方法怎么用”吧!O
    2023-06-30

    Java 中Object的wait() notify() notifyAll()方法使用

    Java 中Object的wait() notify() notifyAll()方法使用一、前言  对于并发编程而言,除了Thread以外,对Object对象的wati和notify对象也应该深入了解其用法,虽然知识点不多。二、线程安全基本
    2023-05-31

    Java Object类怎么使用

    这篇文章主要介绍“Java Object类怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java Object类怎么使用”文章能帮助大家解决问题。1.equals方法==运算符比较运算符,即
    2023-07-02

    怎么重写及应用equals()方法和hashCode()方法

    这篇文章主要介绍“怎么重写及应用equals()方法和hashCode()方法”,在日常操作中,相信很多人在怎么重写及应用equals()方法和hashCode()方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家
    2023-07-05

    object方法如何在java项目中使用

    这篇文章将为大家详细讲解有关object方法如何在java项目中使用,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。正则: “.”和"\""."点儿,在正则表达式中表示任意一个字符。"\"在正
    2023-05-31

    Python中object类特殊方法怎么使用

    这篇“Python中object类特殊方法怎么使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Python中object类
    2023-07-05

    Object toString方法如何在Java项目中使用

    今天就跟大家聊聊有关Object toString方法如何在Java项目中使用,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。一、Object类介绍 Object类在Java里面是一个
    2023-05-31

    java的clone方法怎么使用

    在Java中,clone方法是Object类的一个方法,用于创建并返回一个对象的副本。要使用clone方法,必须实现Cloneable接口并覆盖Object类的clone方法。以下是使用clone方法的步骤:1. 确保类实现了Cloneab
    2023-08-24

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录