Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java hashcode()是否会由于占用空间的压缩而返回不同的int?_Java_Garbage Collection - Fatal编程技术网

Java hashcode()是否会由于占用空间的压缩而返回不同的int?

Java hashcode()是否会由于占用空间的压缩而返回不同的int?,java,garbage-collection,Java,Garbage Collection,如果我在某个对象上调用Object.hashcode()方法,它将返回该对象的内部地址(默认实现)。这个地址是逻辑地址还是物理地址 在垃圾收集中,由于内存压缩,对象在内存中发生移动。如果我在GC之前和之后调用hashcode,它会返回相同的hashcode(它返回),如果是,那么为什么(因为压缩地址可能会改变) 在本文中,它说默认的哈希代码实际上是对象的JVM地址,但如果它被移动,地址将保持一致。 我不知道这个源代码有多可靠,但我确信这个方法的实现者考虑到了这个场景(这不是罕见的或极端的情况),

如果我在某个对象上调用
Object.hashcode()
方法,它将返回该对象的内部地址(默认实现)。这个地址是逻辑地址还是物理地址

在垃圾收集中,由于内存压缩,对象在内存中发生移动。如果我在GC之前和之后调用hashcode,它会返回相同的hashcode(它返回),如果是,那么为什么(因为压缩地址可能会改变)

在本文中,它说默认的哈希代码实际上是对象的JVM地址,但如果它被移动,地址将保持一致。
我不知道这个源代码有多可靠,但我确信这个方法的实现者考虑到了这个场景(这不是罕见的或极端的情况),并确保了这个方法的正确功能。

不,对象的默认哈希代码不会改变

文档并没有说散列码是地址,而是说它基于地址。考虑哈希代码是32位,但有64位JVM。显然,直接使用地址并不总是有效的


实现取决于JVM,但在Sun(Oracle)JVM中,我相信哈希代码在第一次访问时会被缓存。

如果哈希代码发生更改,该对象将在插入的哈希集中消失,Sun将收到大量投诉

根据hashCode的合同,它不能因为这样的原因而改变。

@erickson或多或少是正确的。
java.lang.Object.hashcode()
返回的hashcode在对象的生存期内不会更改

这(通常)的实现方式相当聪明。当垃圾收集器重新定位对象时,必须将其原始哈希代码存储在某个位置,以防再次使用。实现这一点的明显方法是在对象头中添加一个32位字段来保存哈希代码。但这会给每个对象增加1个字的开销,并且在最常见的情况下会浪费空间。。。其中未调用对象的
hashCode
方法

解决方案是向对象的标志字添加两个标志位,并(大致)按如下方式使用它们。调用
hashCode
方法时设置第一个标志。第二个标志告诉
hashCode
方法是使用对象的当前地址作为hashCode,还是使用存储值。当GC运行并重新定位对象时,它会测试这些标志。如果设置了第一个标志,而未设置第二个标志,则GC会在对象末尾分配一个额外的字,并将原始对象位置存储在该字中。然后设置两个标志。从那时起,
hashCode
方法从对象末尾的单词中获取hashCode值


事实上,
identityHashCode
实现必须以这种方式运行,以满足以下部分的要求:

在Java应用程序的执行过程中,每当在同一对象上多次调用hashCode方法时,只要对象上的equals比较中使用的信息未被修改,hashCode方法必须始终返回相同的整数。从一个应用程序的一次执行到同一应用程序的另一次执行,此整数不必保持一致。”


如果GC将对象移动到其他地址,则仅返回对象当前机器地址的
identityHashCode()
的假设实现将违反突出显示的部分。唯一的解决方法是(假设)JVM保证一个对象一旦被调用,就永远不会移动。这将导致堆碎片的严重而棘手的问题。

摘自hashCode的Java文档:这通常是通过将对象的内部地址转换为整数来实现的。实际上,当GC rel如果以前调用过,
hashcode()
,则指定一个对象。实际上,javadoc是这样说的:“这通常是通过将对象的内部地址转换为整数来实现的,但Java不需要这种实现技术™ 实际上,最近的JVM有一个命令行选项,允许您选择其他生成哈希代码的方法“意味着一个根本性的改变,而不是简单的可逆类型转换。如果打印一些
对象.hashCode
的值,您可能会注意到它们不太可能是地址。例如,任何合理实现上的奇数。斯蒂芬,很好的解释!您对hashCode()工作的描述阐明了hashCode()如何在整个程序运行过程中保持相同的值。同时,如果GC+内存压缩发生,并且一个新对象(其hashCode()尚未被调用)被分配与旧对象相同的空间,那么hashCode()值不是与最初占用内存位置的活动对象的值相同吗?这会如何影响对象相等性和基于哈希的集合?我的答案的第3段对此进行了解释。基本上,重新定位对象时,原始地址/哈希代码存储在对象的末尾。但只有在必要时;i、 e.仅当调用了
identityHashcode()
时。我的意思是,Object1的代码为100,并将其复制到Object1末尾的额外单词中。此时,假设发生了GC压缩,并且Object1被移动到其他地方,从而释放其原始内存位置以进行新的分配。假设由于某种巧合,新的Object2以某种方式分配到Object1的旧位置。Object2的哈希代码是什么?不是100美元吗?这意味着Object1(现在移到别处,但最后保存了hashCode 100)和Object2(分配到Object1的旧位置)将共享相同的hashCode@阿什温普拉布