156 votes

Adresse mémoire des variables en Java

Jetez un coup d'œil à l'image ci-dessous. Lorsque nous créons un objet en java avec l'attribut new mot-clé, nous obtenons une adresse mémoire du système d'exploitation.

Lorsque nous écrivons out.println(objName) nous pouvons voir une chaîne "spéciale" en sortie. Mes questions sont les suivantes :

  1. Quelle est cette sortie ?
  2. Si c'est l'adresse mémoire qui nous est donnée par l'OS :

    a) Comment puis-je convertir cette chaîne en binaire ?

    b) Comment puis-je obtenir l'adresse d'une variable entière ?

alt text

5 votes

Je ne vais pas voter contre parce que la question est suffisamment claire, je suggère juste que vous auriez dû la formuler en texte pour que les gens puissent la rechercher.

2 votes

En utilisant le programme sun.misc.Unsafe, il est possible d'obtenir l'adresse d'un objet java. Pour la liste des programmes, voir : javapapers.com/core-java/adresse-d'un-objet-java

0 votes

La valeur pointée est la représentation hexadécimale du code de hachage de l'objet a1 & a2

189voto

Brian Agnew Points 143181

C'est le nom de la classe et System.identityHashCode() séparés par le caractère "@". Ce que représente le code de hachage de l'identité est spécifique à l'implémentation. Il s'agit souvent de l'adresse mémoire initiale de l'objet, mais l'objet peut être déplacé en mémoire par la VM au fil du temps. Donc (brièvement), vous ne pouvez pas compter sur le fait qu'il représente quelque chose.

Obtenir les adresses mémoire des variables n'a aucun sens en Java, puisque la JVM est libre d'implémenter des objets et de les déplacer comme bon lui semble (vos objets peuvent se déplacer ou se déplaceront lors de la collecte des déchets, etc.)

Integer.toBinaryString() vous donnera un nombre entier sous forme binaire.

37 votes

Un autre point intéressant est que codes de hachage d'identité ne sont pas garantis d'être uniques. Par exemple, sur une JVM 64 bits, il existe 2^32 identités. codes de hachage mais 2^64 adresses de mémoire .

14 votes

En fait, le code de hachage de l'identité ne peut pas changer sinon le contrat de hashCode() serait violé.

2 votes

Je l'utilise pour la journalisation/débogage afin de déterminer dans les journaux quand les objets pointent vers le même objet au lieu d'objets équivalents. À ces fins, la méthode identityHashcode n'est pas dénuée de sens, mais elle n'est pas infaillible :)

38voto

JBE Points 998

Il est possible d'utiliser sun.misc.Unsafe : voir cette excellente réponse de @Peter Lawrey ->. Y a-t-il un moyen d'obtenir une adresse de référence ?

Utilisation de son code pour printAddresses() :

    public static void printAddresses(String label, Object... objects) {
    System.out.print(label + ": 0x");
    long last = 0;
    int offset = unsafe.arrayBaseOffset(objects.getClass());
    int scale = unsafe.arrayIndexScale(objects.getClass());
    switch (scale) {
    case 4:
        long factor = is64bit ? 8 : 1;
        final long i1 = (unsafe.getInt(objects, offset) & 0xFFFFFFFFL) * factor;
        System.out.print(Long.toHexString(i1));
        last = i1;
        for (int i = 1; i < objects.length; i++) {
            final long i2 = (unsafe.getInt(objects, offset + i * 4) & 0xFFFFFFFFL) * factor;
            if (i2 > last)
                System.out.print(", +" + Long.toHexString(i2 - last));
            else
                System.out.print(", -" + Long.toHexString( last - i2));
            last = i2;
        }
        break;
    case 8:
        throw new AssertionError("Not supported");
    }
    System.out.println();
}

J'ai mis en place ce test :

    //hashcode
    System.out.println("Hashcode :       "+myObject.hashCode());
    System.out.println("Hashcode :       "+System.identityHashCode(myObject));
    System.out.println("Hashcode (HEX) : "+Integer.toHexString(myObject.hashCode()));

    //toString
    System.out.println("toString :       "+String.valueOf(myObject));

    printAddresses("Address", myObject);

Voici le résultat :

Hashcode :       125665513
Hashcode :       125665513
Hashcode (HEX) : 77d80e9
toString :       java.lang.Object@77d80e9
Address: 0x7aae62270

Conclusion :

  • hashcode != adresse
  • toString = class@HEX(hashcode)

0 votes

(probablement hors sujet mais je suis curieux) Y a-t-il une limitation de 32GB maximum pour l'ensemble du tas ou quelque chose comme ça ?

13voto

Paul Tomblin Points 83687

C'est la sortie de l'implémentation de "toString()" d'Object. Si votre classe surcharge toString(), elle imprimera quelque chose de complètement différent.

10voto

Sunil Kumar Sahoo Points 21032

C'est pas d'adresse mémoire C'est nom de classe@hashcode
qui est l'implémentation par défaut de [Object.toString()](https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#toString())

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

Class name = nom qualifié complet ou nom absolu (c'est-à-dire le nom du paquet suivi du nom de la classe). hashcode = format hexadécimal (System.identityHashCode(obj) ou obj.hashCode() vous donnera le hashcode au format décimal).

Un conseil :
La confusion causée par Root tient au fait que l'implémentation par défaut de l'option [Object.hashCode()](https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode()) utiliser l'adresse interne de l'objet dans un entier

Ceci est typiquement implémenté en convertissant l'adresse interne interne de l'objet en un entier, mais cette technique d'implémentation n'est pas technique n'est pas requise par le langage de programmation Java™.

Et bien sûr, certaines classes peuvent outrepasser les deux implémentations par défaut soit pour toString() o hashCode()

Si vous avez besoin de la valeur d'implémentation par défaut de hashcode() pour un objet qui la surcharge,
Vous pouvez utiliser la méthode suivante System.identityHashCode(Object x)

1voto

James Poulson Points 5505

Ce que vous obtenez est le résultat de la méthode toString() de la classe Object ou, plus précisément, de identityHashCode() comme l'a indiqué uzay95.

"Quand nous créons un objet en Java avec le mot clé new, nous obtenons une adresse mémoire de l'OS."

Il est important de comprendre que tout ce que vous faites en Java est géré par la machine virtuelle Java. C'est la JVM qui donne ces informations. Ce qui se passe réellement dans la RAM du système d'exploitation hôte dépend entièrement de l'implémentation du JRE.

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