J'ai souvent entendu dire que ces méthodes (Object.hashCode
et System.identityHashCode
) renvoient l'adresse de l'objet, ou quelque chose calculé rapidement à partir de l'adresse; mais je suis aussi assez sûr que le ramasse-miettes déplace et compacte les objets. Comme le code de hachage ne peut pas changer, cela pose un problème. Je sais que ce n'est pas quelque chose dont on a besoin de savoir pour le travail quotidien, mais j'aimerais comprendre les détails internes. Alors, est-ce que quelqu'un sait comment c'est implémenté en Java? Ou .NET, étant donné qu'ils sont probablement similaires.
Réponses
Trop de publicités?L'implémentation de .NET n'est intentionnellement pas publiée (et lorsque vous essayez de la décompiler, vous constaterez qu'elle effectue un appel de framework non géré). La seule documentation à ce sujet est ici, qui indique seulement qu'elle n'est pas garantie de produire une valeur différente pour chaque objet, et peut changer entre les versions du framework. Faire des hypothèses sur son fonctionnement réel est probablement déconseillé.
Celle de Java est plus comprise (bien que potentiellement différente selon les JVM), et est spécifiquement abordée dans cette question: Will .hashcode() return a different int due to compaction of tenure space?
L'idée générale de l'implémentation en Java est que, par contrat, la valeur du hashcode d'un objet n'est pas pertinente tant qu'elle n'est pas récupérée pour la première fois. Après cela, elle doit rester constante. Ainsi, le déplacement de l'objet par le GC n'a pas d'importance tant que la méthode hashcode() de l'objet n'est pas appelée pour la première fois. Après cela, une valeur mise en cache est utilisée.
L'identityHashCode ne change pas pour un objet. Ainsi, tout déplacement se fait en dessous de ce niveau.
Une implémentation rudimentaire aurait une correspondance d'adresse logique --> adresse physique pour chaque objet.
Les implémentations plus sophistiquées n'auraient la correspondance qu'au niveau de la page, donc peut-être que les 6 derniers bits sont le décalage mémoire, et le reste est l'identifiant de la page. L'indirection se ferait au niveau de l'identifiant de la page --> adresse de la page réelle.
En .net, la méthode getHash() sera impactée par le GC et il est donc recommandé aux développeurs d'utiliser leurs propres implémentations de hash. Je ne trouve pas le lien vers l'implémentation interne pour le moment. Je le posterai plus tard si je le trouve.
J'ai trouvé le lien... Cette question a été répondue ici