Dirección de memoria de variables en Java

139

Por favor, eche un vistazo a la imagen de abajo. Cuando creamos un objeto en java con la newpalabra clave, estamos obteniendo una dirección de memoria del sistema operativo.

Cuando escribimos out.println(objName)podemos ver una cadena "especial" como salida. Mis preguntas son:

  1. ¿Cuál es esta salida?
  2. Si es la dirección de memoria que nos ha proporcionado el sistema operativo:

    a) ¿Cómo puedo convertir esta cadena a binario?

    b) ¿Cómo puedo obtener una dirección de variables enteras?

texto alternativo

uzay95
fuente
55
bueno, no voy a rechazar porque la pregunta es lo suficientemente clara, solo una sugerencia de que deberías haberla hecho en texto para que la gente pueda buscarla
Phunehehe
2
Usando sun.misc.Unsefe es posible obtener la dirección de un objeto java. Para obtener una lista del programa, consulte: javapapers.com/core-java/address-of-a-java-object
Joseph Kulandai
el valor señalado es la representación hexadecimal del código hash del objeto a1 y a2
Naveen

Respuestas:

167

Ese es el nombre de clase y System.identityHashCode () separados por el carácter '@'. Lo que representa el código hash de identidad es específico de la implementación. A menudo es la dirección de memoria inicial del objeto, pero la máquina virtual puede mover el objeto en la memoria con el tiempo. Entonces (brevemente) no puedes confiar en que sea algo.

Obtener las direcciones de memoria de las variables no tiene sentido en Java, ya que la JVM es libre de implementar objetos y moverlos como parece (sus objetos pueden moverse durante la recolección de basura, etc.)

Integer.toBinaryString () le dará un número entero en forma binaria.

Brian Agnew
fuente
33
Otro punto interesante es que no se garantiza que los códigos hash de identidad sean únicos. Por ejemplo, en JVM de 64 bits hay 2 ^ 32 códigos hash de identidad pero 2 ^ 64 direcciones de memoria .
Alex Jasmin
11
En realidad, el código hash de identidad no puede cambiar , de lo contrario se violaría el contrato de hashCode ().
Matt McHenry
1
Estoy usando esto para registrar / depurar para determinar en los registros cuando los objetos apuntan al mismo objeto en lugar de los equivalentes. Para estos propósitos, identityHashcodeno tiene sentido, simplemente no es infalible. :)
Trineo
@BrianAgnew: Quiero saber -> Por qué dos objetos tienen el mismo código hash. Estoy confundido porque he aprendido en c o c ++ cada variable u objeto tiene una ubicación de memoria diferente. Luego, en Java, cómo se pueden identificar o diferenciar dos objetos con el mismo hashCode.
Ved Prakash
1
@VedPrakash, el código hash del objeto permite que los objetos se almacenen en colecciones hash. Si desea diferenciar dos objetos diferentes, simplemente puede usar la igualdad de referencia
Brian Agnew
36

Es posible usar sun.misc.Unsafe: vea esta gran respuesta de @Peter Lawrey -> ¿Hay alguna manera de obtener una dirección de referencia?

Usando su código para 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();
}

Configuré esta prueba:

    //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);

Aquí está la salida:

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

Conclusión

  • hashcode! = dirección
  • toString = class @ HEX (código hash)
JBE
fuente
13

Esa es la salida de la implementación "toString ()" de Object. Si su clase anula aString (), imprimirá algo completamente diferente.

Paul Tomblin
fuente
6

Esta no es la dirección de memoria Este es classname @ hashcode

dónde

nombre de clase = nombre completo calificado o nombre absoluto (es decir, nombre del paquete seguido del nombre de la clase)

hashcode = formato hexadecimal (System.identityHashCode (obj) u obj.hashCode () le dará un código hash en formato decimal)

Sunil Kumar Sahoo
fuente
4

Como dijo Sunil, esta no es una dirección de memoria . Es solo el código hash

Para obtener el mismo contenido @, puede:

Si hashCode no se anula en esa clase:

"@" + Integer.toHexString(obj.hashCode())

Si se anula hashCode, obtiene el valor original con:

"@" + Integer.toHexString(System.identityHashCode(obj)) 

Esto a menudo se confunde con la dirección de memoria porque si no anula hashCode (), la dirección de memoria se usa para calcular el hash.

Topera
fuente
1

Lo que está obteniendo es el resultado del método toString () de la clase Object o, más precisamente, el identityHashCode () como ha señalado uzay95.

"Cuando creamos un objeto en Java con una nueva palabra clave, estamos obteniendo una dirección de memoria del sistema operativo".

Es importante darse cuenta de que todo lo que hace en Java es manejado por la máquina virtual de Java. Es la JVM la que está dando esta información. Lo que realmente sucede en la RAM del sistema operativo host depende completamente de la implementación del JRE.

James P.
fuente
0

En Java, cuando está creando un objeto de una clase como Person p = new Person();, en prealidad es una dirección de una ubicación de memoria que apunta a un tipo de Person.

Cuando use un statemenet para imprimir p, verá una dirección. La newpalabra clave crea una nueva ubicación de memoria que contiene todas las variables de instancia y métodos que se incluyen class Persony pes la variable de referencia que apunta a esa ubicación de memoria.

Panduka Wedisinghe
fuente
en su imagen, a1 y a2 son dos direcciones de memoria diferentes. Esa es la razón detrás de obtener dos valores diferentes.
Panduka Wedisinghe