String.hashCode () est-il portable sur les ordinateurs virtuels, les JDK et les systèmes d’exploitation?

StackOverflow https://stackoverflow.com/questions/190376

  •  06-07-2019
  •  | 
  •  

Question

Un problème intéressant a été soulevé récemment. Nous sommes tombés sur un code qui utilise hashCode () comme source de sel pour le cryptage MD5, mais cela soulève la question suivante: hashCode () renverra-t-il la même valeur pour le même objet sur différentes machines virtuelles, différentes versions de JDK et systèmes d'exploitation? Même si ce n'est pas garanti, cela a-t-il changé depuis le début?

EDIT: Je veux vraiment dire String.hashCode () plutôt que le plus général Object.hashCode () , qui peut bien sûr être remplacé.

Était-ce utile?

La solution

Non. De http://tecfa.unige.ch/guides/java/ langspec-1.0 / javalang.doc1.html :

  

Le contrat général de hashCode est le suivant:   suit:

     
      
  • Chaque fois qu'il est appelé plus d'une fois sur le même objet au cours d'une   exécution d'une application Java,   hashCode doit toujours renvoyer le   même nombre entier. Le nombre entier peut être   positif, négatif ou nul. Ce   entier ne doit cependant pas   rester cohérent d'un Java   application à un autre, ou à un autre   exécution d'une application à une autre   exécution de la même application.   [...]
  •   

Autres conseils

Cela dépend du type:

  • Si vous avez un type qui n'a pas remplacé hashCode (), il retournera probablement un hashCode () différent à chaque fois que vous exécuterez le programme.
  • Si vous avez un type qui remplace hashCode () mais ne documente pas la manière dont il est calculé, il est parfaitement légitime qu'un objet avec les mêmes données renvoie un hachage différent à chaque exécution, tant qu'il renvoie le même. hachage pour les appels répétés dans la même exécution.
  • Si vous avez un type qui redéfinit hashCode () de manière documentée, c'est-à-dire que l'algorithme fait partie du comportement documenté, vous êtes probablement en sécurité. (java.lang.String documente cela, par exemple.) Cependant, je voudrais tout de même éviter que se fie à cela sur un principe général, personnellement.

Juste un récit édifiant du monde .NET: j'ai vu au moins quelques personnes dans un monde de douleur en utilisant le résultat de string.GetHashCode () comme mot de passe haché dans une base de données. L'algorithme a changé entre .NET 1.1 et 2.0, et soudainement tous les hachages sont "faux". (Jeffrey Richter documente un cas presque identique dans CLR via C #.) Quand un hachage doit être stocké, je préférerais qu'il soit calculé de manière toujours garantie d'être stable - par exemple MD5 ou une interface personnalisée implémentée par vos types avec une garantie de stabilité.

Selon le docs : le code de hachage d'un objet String est calculé comme

s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

Je ne suis pas certain qu'il s'agisse d'une spécification formelle ou simplement de la mise en œuvre de Sun. À tout le moins, il devrait être identique sur toutes les machines virtuelles Sun existantes, quelle que soit la plate-forme ou le système d'exploitation.

Non. Les algorithmes de hachage ne sont pas garantis, sauf indication contraire. Ainsi, par exemple, la désérialisation des structures de hachage doit recalculer les codes de hachage, et ces valeurs ne doivent pas être stockées sous la forme sérialisée.

Je voudrais ajouter que vous pouvez remplacer hashCode () (n'oubliez pas égal à () si vous faites cela) pour vous assurer que vos objets métier renvoient le même hashCode partout. Ces objets auront alors au moins un hashCode prévisible.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top