java中的hashcode怎么重写(java 无参方法中显示各属性的信息)

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

本文主要讲解“如何使用javaObject的hashCode方法”,简单明了,易学易懂。接下来,请跟随边肖的思路,一起学习学习“如何使用javaObject的hashCode方法”!

00-1010重写hashCode方法时,我很好奇的看到hashCode打印出来的数据看起来像一个地址值。

另外,我最近在研究jvm源代码,所以想了解一下hashCode是如何在hotspot中实现的。

1. 背景介绍

2. 调用过程梳理

publinativeinthashcode();通过官方jdk Object.class的源代码,发现hashCode被native修改了。因此,这种方法应该由C/C在jvm中实现。

00-1010首先观察对应于Object.java的对象代码。

//文件路径: JDK \ src \ share \ native \ Java \ lang \ object . c

staticninativmethodsmethods[]={ 0

{'hashCode ','()I ',(void *) JVM _ ihashcode},//这个方法就是我们想看到的hashCode方法。

{'wait ','(J)V ',(void*)JVM_MonitorWait},

{'notify ','()V ',(void *)JVM _ monitornify },

{'notifyAll ','()V ',(void *)JVM _ monitornityall },

{'clone ','()Ljava/lang/Object;',(void*)JVM_Clone},

};在jvm.h文件中,这个文件包含许多java调用本机方法的接口。

//热点\src\share\vm\prims\jvm.h

/*

*java.lang.Object

*/

JNIEXPORTjintJNICALL

JVM_IHashCode(JNIEnv*env,job object obj);//此时定义了hashCode方法的接口,具体在jvm.cpp //hotspot\src\s中实现

hare\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::FastHashCode
JVM_END

进入到ObjectSynchronizer::FastHashCode

// hotspot\src\share\vm\runtime\synchronizer.cpp
intptr_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\src\share\vm\runtime\synchronizer.cpp
static 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\src\share\vm\oops\markOop.hpp
class 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;
/***
 * 可以通过系列参数指定hashCode生成策略
 * -XX:hashCode=2
 */
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策略值 描述
1 0 直接通过随机数生成
2 1 通过object地址和随机数运算生成
3 2 永远返回1, 用于测试
4 3 返回一个全局递增的序列数
5 4 直接采用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方法怎么使用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/155203.html

(0)

相关推荐

  • C#框架的总体设计知识点有哪些

    技术C#框架的总体设计知识点有哪些本篇内容介绍了“C#框架的总体设计知识点有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有

    攻略 2021年11月26日
  • 抖音点赞在线自助平台网站,抖音点赞自助购买平台?

    技术抖音点赞在线自助平台网站,抖音点赞自助购买平台?抖音刷赞自助网站,抖音点赞自助购买平台操作流程,一些大牌厂商也已经入驻,发展前景非常可观,在带来欢乐的同时也成为营销的重要平台,这样一个,又有趣,又能挣钱,路子又正,用

    测评 2021年10月26日
  • 你知道 Java 代码是如何运行的吗

    技术你知道 Java 代码是如何运行的吗 你知道 Java 代码是如何运行的吗对于任何一门语言,要想达到精通的水平,研究它的执行原理(或者叫底层机制)不失为一种良好的方式。
    在本篇文章中,将重点研究ja

    礼包 2021年11月29日
  • 汉语拼音v的读音,汉语拼音v的读音是什么

    技术汉语拼音v的读音,汉语拼音v的读音是什么v对应汉语拼音中的ü (发‘迂’的音)汉语拼音中的ü是我国特有的,只是针对汉语的一个音符.而V是就国际标准而言的,他是国际音标的一个,是全世界通用的,所以,一般在电脑中没有ü,

    生活 2021年10月27日
  • Does RSA Private key always contain the Public key, or is it just .NET

    技术Does RSA Private key always contain the Public key, or is it just .NET Does RSA Private key always

    礼包 2021年12月9日
  • 如何用免费代理IP爬数据

    技术如何用免费代理IP爬数据如何用免费代理IP爬数据,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。一.前言玩爬虫的都避免不了各大网站的反爬措施限制,比较常见

    攻略 2021年10月28日