java - sirve - Will.hashcode() devolverá un int diferente debido a la compactación del espacio de tenencia?
object equals java (5)
@erickson es más o menos correcto. El código hash devuelto por java.lang.Object.hashCode()
no cambia durante la vigencia del objeto.
La forma en que esto (típicamente) se implementa es bastante inteligente. Cuando un objeto es reubicado por el recolector de basura, su hashcode original debe almacenarse en algún lugar en caso de que se vuelva a utilizar. La forma obvia de implementar esto sería agregar un campo de 32 bits al encabezado del objeto para contener el código hash. Pero eso agregaría una sobrecarga de 1 palabra a cada objeto, y desperdiciaría espacio en el caso más común ... donde no se llama al método hashCode
un Objeto.
La solución es agregar dos marcadores a la palabra de bandera del objeto y usarlos (más o menos) de la siguiente manera. El primer indicador se establece cuando se hashCode
método hashCode
. Un segundo indicador le dice al método hashCode
si usar la dirección actual del objeto como hashCode
, o usar un valor almacenado. Cuando el GC se ejecuta y reubica un objeto, prueba estos indicadores. Si se establece el primer indicador y el segundo no está configurado, el GC asigna una palabra adicional al final del objeto y almacena la ubicación del objeto original en esa palabra. Luego establece las dos banderas. Desde ese momento, el método hashCode
obtiene el valor del hashCode
de la palabra al final del objeto.
De hecho, una implementación de identityHashCode
tiene que comportarse de esta manera para satisfacer la siguiente parte del contrato hashCode general :
"Cada vez que se invoca en el mismo objeto más de una vez durante una ejecución de una aplicación Java, el método hashCode debe devolver consistentemente el mismo entero, siempre que no se modifique la información utilizada en comparaciones iguales en el objeto . Este entero no tiene que ser coherente desde una ejecución de una aplicación a otra ejecución de la misma aplicación ".
Una implementación hipotética de identityHashCode()
que simplemente devolvió la dirección actual de la máquina de un objeto violaría la parte resaltada si / cuando el GC movía el objeto a una dirección diferente. La única forma de evitar esto sería que la JVM (hipotética) garantice que un objeto nunca se mueve una vez que ha sido invocado hashCode
. Y eso llevaría a problemas serios e intratables con la fragmentación del montón.
Si Object.hashcode()
método Object.hashcode()
en algún objeto, devuelve la dirección interna del objeto (implementación predeterminada). ¿Es esta dirección una dirección lógica o física?
En la recolección de basura, debido a la compactación de memoria, los objetos cambian en la memoria. Si llamo a hashcode antes y después del GC, ¿devolverá el mismo código hash (regresa) y, en caso afirmativo, entonces por qué (debido a que la dirección de compactación puede cambiar)?
En este link , dice que, de hecho, el código hash predeterminado es la dirección JVM del objeto, pero si se mueve, la dirección permanece constante. No sé qué tan confiable es esta fuente, pero estoy seguro de que los implementadores de este método pensaron en este escenario (que no es raro o caso de esquina), y garantizaron la funcionalidad correcta de este método.
No, el código hash predeterminado de un objeto no cambiará.
La documentación no dice que el código hash es la dirección, dice que está basado en la dirección. Tenga en cuenta que los códigos hash son 32 bits, pero hay JVM de 64 bits. Claramente, el uso directo de la dirección no siempre funcionaría.
La implementación depende de la JVM, pero en la JVM de Sun (Oracle), creo que el código hash se almacena en la memoria caché la primera vez que se accede a él.
si el hashcode cambia, el objeto desaparecerá en un hash en el que se insertó, y Sun se verá inundado de quejas.
Por el contrato de hashCode no puede cambiar por tal motivo.