Endereço de memória das variáveis ​​em Java


139

Por favor, dê uma olhada na imagem abaixo. Quando criamos um objeto em java com a newpalavra - chave, estamos obtendo um endereço de memória do sistema operacional.

Quando escrevemos out.println(objName), podemos ver uma string "especial" como saída. Minhas perguntas são:

  1. O que é essa saída?
  2. Se é o endereço de memória que nos foi dado pelo SO:

    a) Como posso converter essa string para binária?

    b) Como posso obter um endereço de variáveis ​​inteiras?

texto alternativo


5
bem, eu não estou votando para baixo, porque a questão é clara o suficiente, apenas uma sugestão que você deveria ter feito para que as pessoas podem procurá-lo-lo em texto
phunehehe

2
Usando o sun.misc.Unsafe, é possível obter o endereço de um objeto java. Para obter uma lista de programas, consulte: javapapers.com/core-java/address-of-a-java-object
Joseph Kulandai

o valor apontado é a representação hexadecimal do código hash do objeto a1 e a2
Naveen

Respostas:


166

Esse é o nome da classe e System.identityHashCode () separados pelo caractere '@'. O que o código de hash de identidade representa é específico da implementação. Geralmente, é o endereço de memória inicial do objeto, mas o objeto pode ser movido na memória pela VM ao longo do tempo. Então (brevemente) você não pode confiar que seja qualquer coisa.

Obter os endereços de memória das variáveis ​​não faz sentido no Java, pois a JVM tem liberdade para implementar objetos e movê-los conforme parecer adequado (seus objetos podem / se moverão durante a coleta de lixo etc.)

Integer.toBinaryString () fornecerá um número inteiro em formato binário.


33
Outro ponto interessante é que não é garantido que os códigos de hash de identidade sejam exclusivos. Por exemplo, na JVM de 64 bits, existem 2 ^ 32 códigos de hash de identidade, mas 2 ^ 64 endereços de memória .
Alex Jasmin

11
Na verdade, o código de hash de identidade não pode ser alterado , caso contrário, o contrato de hashCode () seria violado.
Matt McHenry

1
Eu estou usando isso para log / depuração para determinar nos logs quando objetos estão apontando para o mesmo objeto em vez de equivalentes. Para esses propósitos identityHashcode, isso não tem sentido, apenas não é infalível. :)
Sled

@ BrianAgnew: Eu quero saber -> Por que dois objetos têm o mesmo código de hash. Estou confuso porque aprendi em c ou c ++ que cada variável ou objeto tem um local de memória diferente. Então, em java, como identificar ou diferenciar dois objetos com o mesmo hashCode.
Ved Prakash

1
@VedPrakash, o hashcode do objeto permite que os objetos sejam armazenados em coleções de hash. Se você quiser diferenciar dois objetos diferentes, você poderia simplesmente usar igualdade de referência
Brian Agnew

36

É possível usar sun.misc.Unsafe: veja esta ótima resposta de Peter Lawrey -> Existe uma maneira de obter um endereço de referência?

Usando seu 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();
}

Eu configurei este teste:

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

Aqui está a saída:

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

Conclusão:

  • hashcode! = endereço
  • toString = classe @ HEX (código de hash)

13

Essa é a saída da implementação "toString ()" do objeto. Se sua classe substituir toString (), ela imprimirá algo completamente diferente.


6

Este não é o endereço da memória Este é classname @ hashcode

Onde

nome da classe = nome completo qualificado ou nome absoluto (ou seja, nome do pacote seguido pelo nome da classe)

hashcode = formato hexadecimal (System.identityHashCode (obj) ou obj.hashCode () fornecerá código de hash no formato decimal)


4

Como Sunil disse, este não é um endereço de memória . Este é apenas o código hash

Para obter o mesmo conteúdo @, você pode:

Se o hashCode não for substituído nessa classe:

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

Se hashCode for substituído, você obterá o valor original com:

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

Isso geralmente é confundido com o endereço de memória, porque se você não substituir o hashCode (), o endereço de memória será usado para calcular o hash.


1

O que você está obtendo é o resultado do método toString () da classe Object ou, mais precisamente, o identityHashCode () como o uzay95 apontou.

"Quando criamos um objeto em java com a nova palavra-chave, estamos obtendo um endereço de memória do sistema operacional".

É importante perceber que tudo o que você faz em Java é tratado pela Java Virtual Machine. É a JVM que está fornecendo essas informações. O que realmente acontece na RAM do sistema operacional host depende inteiramente da implementação do JRE.



0

Em Java, quando você cria um objeto de uma classe como Person p = new Person();, pna verdade é um endereço de um local de memória que está apontando para um tipo de Person.

Ao usar um conjunto de estatísticas para imprimir, pvocê verá um endereço. A newpalavra-chave cria um novo local de memória que contém todas as variáveis ​​e métodos de instância incluídos class Persone pé a variável de referência que aponta para esse local de memória.


na foto a1 e a2 existem dois endereços de memória diferentes. essa é a razão por trás da obtenção de dois valores diferentes.
você precisa saber é o seguinte
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.