75 votes

Comment la JVM s'assure-t-elle que System.identityHashCode() ne changera jamais ?

En règle générale, l'implémentation par défaut de Object.hashCode() est une fonction de l'adresse allouée de l'objet en mémoire (bien que cela ne soit pas imposé par la norme JLS ). Étant donné que la VM déplace les objets en mémoire, pourquoi la valeur renvoyée par System.identityHashCode() ne changent jamais pendant la durée de vie de l'objet ?

S'il s'agit d'un calcul "one-shot" (l'objet hashCode est calculé une fois et caché dans l'en-tête de l'objet ou quelque chose comme ça), cela signifie-t-il qu'il est possible pour deux objets d'avoir le même identityHashCode (s'ils sont alloués pour la première fois à la même adresse dans la mémoire) ?

1 votes

Question connexe : Cette adresse mémoire est-elle une adresse mémoire réelle ou quelque chose de virtuel qui peut rester fixe même si l'objet est déplacé ? Si elle est virtuelle, ce serait une bonne chose car les pointeurs vers cette adresse n'auraient pas besoin d'être ajustés. D'un autre côté, cela signifierait une indirection supplémentaire et une table de correspondance potentiellement importante.

3 votes

Il s'agit d'un léger réarrangement de l'adresse lors de la première demande. (Renvoyer un code de hachage dont les bits de poids faible sont tous nuls n'est pas génial).

0 votes

En fait, où est-il indiqué que l'identityHashCode ne doit jamais changer ? La JavaDoc pour System.identityHashCode n'est pas claire à ce sujet.

44voto

Tom Hawtin - tackline Points 82671

Les JVM modernes enregistrent la valeur dans l'en-tête de l'objet. Je pense que la valeur n'est généralement calculée que lors de la première utilisation afin de réduire au minimum le temps consacré à l'allocation de l'objet (parfois jusqu'à une douzaine de cycles). La JVM Sun courante peut être compilée de manière à ce que le code de hachage d'identité soit toujours égal à 1 pour tous les objets.

Plusieurs objets peuvent avoir le même code de hachage d'identité. C'est la nature même des codes de hachage.

6 votes

Je viens de regarder ObjectSynchronizer::FastHashCode dans synchronizer.cpp (code source de la vm) et après avoir généré le code de hachage, il semble qu'il le fusionne dans l'en-tête de l'objet. Il semble qu'il y ait plusieurs implémentations possibles de HashCode ; celle à laquelle vous faites allusion et qui renvoie 1 pour tous les objets est utilisée pour s'assurer qu'aucune partie de la VM ne suppose que les codes de hachage sont uniques pour quelque raison que ce soit.

0 votes

Public static native int identityHashCode(Object x) ; est une méthode native. Pouvez-vous l'expliquer du point de vue du code natif implémenté ? Je veux dire l'implémentation C++. Elle est principalement utilisée dans inIdentityHashMap, n'est-ce pas ?

0 votes

@Tom Qu'entendez-vous par en-tête d'objet ? Vous avez également écrit : " Je crois que la valeur n'est généralement calculée que lors de la première utilisation afin de maintenir l'allocation d'objet au minimum (parfois jusqu'à une douzaine de cycles) ". Pouvez-vous expliquer à quelle allocation d'objet vous faites référence ici ?

17voto

Stephen Denne Points 17031

En réponse à la deuxième question, quelle que soit l'implémentation, il est possible que plusieurs objets aient le même code de hachage d'identité (identityHashCode).

Voir bug 6321873 pour une brève discussion sur la formulation dans la javadoc, et un programme pour démontrer la non-unicité.

1 votes

C'est vrai. Deux objets différents peuvent avoir le même hashCode. C'est le cas de toutes les fonctions de hachage (sur un domaine plus grand que la taille de leur résultat).

1 votes

@Thilo : La JVM aurait pu être écrite de manière à garantir cela, à condition qu'il n'y ait jamais plus de quatre milliards d'objets en existence en même temps, identityHashCode ne renverra jamais une valeur qui a été renvoyée avec un autre objet encore existant. Selon la manière dont le gestionnaire de mémoire est mis en œuvre, cela peut être coûteux ou n'ajouter aucun coût supplémentaire. Par exemple, un Object pourrait contenir un index dans une table de pointeurs, chaque objet se voyant attribuer de manière immuable un emplacement dans la table tant qu'il existe. Les implémentations typiques de la JVM ne font pas cela...

0 votes

...mais d'autres systèmes de gestion de la mémoire "basés sur les poignées" le font, il peut donc être utile de documenter le fait que la JVM choisit essentiellement un nombre arbitraire la première fois qu'un objet est invité à fournir son code de hachage d'identité, puis le stocke pour une utilisation ultérieure [btw, je ne me souviens pas avoir lu quoi que ce soit pour documenter officiellement le fait que la JVM a choisi un nombre arbitraire la première fois qu'un objet est invité à fournir son code de hachage d'identité, puis le stocke pour une utilisation ultérieure]. identityHashcode n'est pas soumis à des contraintes de temps. Si le code de hachage d'un objet n'a jamais été récupéré, existe-t-il une garantie que les "premiers" appels simultanés à identityHashCode sur cet objet produira la même valeur ?

2voto

Lii Points 690

L'en-tête d'un objet dans HotSpot se compose d'un pointeur de classe et d'un mot "mark".

Le code source de la structure de données pour le mot-clé se trouve à l'adresse suivante markOop.hpp fichier. Ce fichier contient un commentaire décrivant la disposition de la mémoire du mot-clé :

hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object)

Nous voyons ici que le code de hachage d'identité pour les objets Java normaux sur un système 32 bits est enregistré dans le mot de marque et qu'il a une longueur de 25 bits.

0voto

Gishu Points 59012

La ligne directrice générale pour la mise en œuvre d'une fonction de hachage est la suivante :

  • le même objet doit renvoyer un hashCode cohérent Il ne doit pas changer avec le temps ni dépendre d'informations variables (par exemple, un algorithme alimenté par un nombre aléatoire ou des valeurs de champs membres mutables).
  • la fonction de hachage doit avoir un bonne distribution aléatoire Si l'on considère le code de hachage comme un ensemble, deux objets doivent correspondre à des ensembles (codes de hachage) différents, dans la mesure du possible. La possibilité que deux objets aient le même code de hachage devrait être rare - bien qu'il soit possible que le code de hachage de deux objets soit différent. puede se produisent.

-6voto

Mnementh Points 19831

Pour autant que je sache, cette fonction est mise en œuvre pour renvoyer la référence, qui ne changera jamais au cours de la durée de vie d'un objet.

0 votes

Vous dites donc que la référence n'est pas une adresse mémoire réelle (ou directement dérivée de celle-ci). S'agit-il donc d'une sorte de pointeur vers l'adresse mémoire réelle ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X