热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

为什么Object.hashCode()在运行中返回相同的值

如何解决《为什么Object.hashCode()在运行中返回相同的值》经验,为你挑选了2个好方法。

hashCode()HotSpot 的默认实现返回一个随机值并将其存储在对象头中.这在Java 8中似乎没有改变,其中哈希值是通过调用来计算的os::random():

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
...

我想知道为什么hashCode()在关闭JVM之后不断返回相同的值,我通过执行下面的简单测试,重新启动机器然后main()再次运行来尝试.

public class SimpleTest {
  public static void main(String[] args) {
    Object obj = new Object();
    // This calls toString() which calls hashCode() which calls os::random()
    System.out.println(obj);
  }
}

如果hashCode()实际上每次输出如何相同os::random()


java -version

java version "1.8.0_40"
Java(TM) SE Runtime Environment (build 1.8.0_40-b25)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)

注意:

如果有人问自己是什么System.out.println(obj);,它调用 obj.toString()该对象是否非空,产生类似java.lang.Object@659e0bfd,有做hashCode():后一部分@是对象的散列码十六进制(和是无关的,在内存中的对象的位置,相反给什么文件表明,这导致了误解).



1> David Schwar..:

确定性行为使代码更容易调试,因为它可以被复制.所以实现倾向于在可能的情况下选择.想象一下,如果哈希每次都不同,那么复制一些由于错误处理哈希冲突而失败的单元测试(例如,在哈希长度缩短之后)是多么困难.


这似乎不是一个很好的理由; 如果您正在编写依赖于`.hashCode()`行为的测试,那么您应该测试已明确定义`.hashCode()`方法的对象.依靠`Object.hashCode()`保持稳定只会引发问题,特别是升级JVM版本时.如果有的话,这是一个在运行之间显式地使`Object.hashCode()`volatile的参数.

2> dimo414..:

要回答你的问题,我们首先要问第二个问题,"为什么os::random()种子会固定种子?"

正如@DavidSchwartz所说,拥有一个带有固定种子的"随机"数字生成器非常有用,因为它可以为您提供任意但确定的行为.JVM开发人员可以调用os::random()并且仍然知道JVM的行为不依赖于任何外部因素.除了其他好处之外,这意味着JVM测试是可重复的; 使用"适当"种子RNG将难以重现与RNG相关的故障.

现在我们可以回答原来的问题,改写为"为什么HotSpot的实现Object.hashCode()使用os::random()?"

这个问题的答案很可能只是因为它很简单,而且很有效.哈希码需要分布均匀,这是RNG提供的.JVM的这个区域中最简单,最容易访问的RNG是os::random().由于Object.hashCode()不能保证这些值的来源,因此根本不是os::random()随机的并不重要.

您会注意到这只是一种可能的散列策略,其他几种定义(并由hashCode全局选择),包括它们" 可能会成为......未来版本中的默认值 ".

最终,这只是一个实现细节.没有必要更积极地随机化Object.hashCode(),并且完全有可能其他JVM不这样做,或者其他操作系统表现不同.实际上,在Eclipse中,我反复运行代码时会看到不同的哈希码.此外,合同Object.hashCode()建议典型的JVM实现根本不实现Object.hashCode()这种方式:

这通常通过将对象的内部地址转换为整数来实现


另请注意,您的测试仅验证第一次调用.hashCode()是否一致.在任何类型的多线程程序中,您都不能指望这种行为.它还可以os::random()在执行期间依赖于JVM调用中的任何其他内容,它可以随时执行(例如,如果垃圾收集器在第一个GC将是非确定性之后依赖于调用os::random()的结果.hashCode()).


推荐阅读
  • Java程序设计第4周学习总结及注释应用的开发笔记
    本文由编程笔记#小编为大家整理,主要介绍了201521123087《Java程序设计》第4周学习总结相关的知识,包括注释的应用和使用类的注释与方法的注释进行注释的方法,并在Eclipse中查看。摘要内容大约为150字,提供了一定的参考价值。 ... [详细]
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • 本文讨论了如何使用Web.Config进行自定义配置节的配置转换。作者提到,他将msbuild设置为详细模式,但转换却忽略了带有替换转换的自定义部分的存在。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • VueCLI多页分目录打包的步骤记录
    本文介绍了使用VueCLI进行多页分目录打包的步骤,包括页面目录结构、安装依赖、获取Vue CLI需要的多页对象等内容。同时还提供了自定义不同模块页面标题的方法。 ... [详细]
  • GreenDAO快速入门
    前言之前在自己做项目的时候,用到了GreenDAO数据库,其实对于数据库辅助工具库从OrmLite,到litePal再到GreenDAO,总是在不停的切换,但是没有真正去了解他们的 ... [详细]
  • Hibernate延迟加载深入分析-集合属性的延迟加载策略
    本文深入分析了Hibernate延迟加载的机制,特别是集合属性的延迟加载策略。通过延迟加载,可以降低系统的内存开销,提高Hibernate的运行性能。对于集合属性,推荐使用延迟加载策略,即在系统需要使用集合属性时才从数据库装载关联的数据,避免一次加载所有集合属性导致性能下降。 ... [详细]
  • 使用nodejs爬取b站番剧数据,计算最佳追番推荐
    本文介绍了如何使用nodejs爬取b站番剧数据,并通过计算得出最佳追番推荐。通过调用相关接口获取番剧数据和评分数据,以及使用相应的算法进行计算。该方法可以帮助用户找到适合自己的番剧进行观看。 ... [详细]
  • 在Kubernetes上部署JupyterHub的步骤和实验依赖
    本文介绍了在Kubernetes上部署JupyterHub的步骤和实验所需的依赖,包括安装Docker和K8s,使用kubeadm进行安装,以及更新下载的镜像等。 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文讨论了如何在dotnet桌面(Windows)应用程序中添加图标。作者提到可以使用dotnet命令行工具与resource.rc文件一起使用来为标准.NET核心应用程序添加图标。作者还介绍了在创建控制台应用程序时如何编辑projeto1.csproj文件来添加图标。 ... [详细]
  • 树莓派语音控制的配置方法和步骤
    本文介绍了在树莓派上实现语音控制的配置方法和步骤。首先感谢博主Eoman的帮助,文章参考了他的内容。树莓派的配置需要通过sudo raspi-config进行,然后使用Eoman的控制方法,即安装wiringPi库并编写控制引脚的脚本。具体的安装步骤和脚本编写方法在文章中详细介绍。 ... [详细]
  • 本文介绍了在CentOS 6.4系统中更新源地址的方法,包括备份现有源文件、下载163源、修改文件名、更新列表和系统,并提供了相应的命令。 ... [详细]
author-avatar
谢海武181_160
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有