Java 변수의 메모리 주소


139

아래 그림을 참조하십시오. new키워드를 사용하여 java에서 객체를 만들면 OS에서 메모리 주소를 얻습니다.

우리가 쓸 때 out.println(objName)"특별한"문자열을 출력으로 볼 수 있습니다. 내 질문은 :

  1. 이 결과는 무엇입니까?
  2. OS가 우리에게 제공 한 메모리 주소 인 경우 :

    a)이 문자열을 이진수로 어떻게 변환 할 수 있습니까?

    b) 하나의 정수 변수 주소를 어떻게 얻을 수 있습니까?

대체 텍스트


5
글쎄, 나는 질문이 충분히 명확하기 때문에 투표하지 않습니다. 사람들이 검색 할 수 있도록 텍스트로 작성해야한다는 제안
일뿐

2
sun.misc.Unsafe를 사용하면 Java 객체의 주소를 얻을 수 있습니다. 프로그램 목록은 javapapers.com/core-java/address-of-a-java-object를
Joseph Kulandai

지정된 값은 객체 a1 & a2의 해시 코드의 16 진 표현입니다
Naveen

답변:


166

클래스 이름과 System.identityHashCode () 는 '@'문자로 구분됩니다. 아이덴티티 해시 코드가 나타내는 것은 구현에 따라 다릅니다. 종종 개체의 초기 메모리 주소이지만 시간이 지남에 따라 VM에서 개체를 메모리에서 이동할 수 있습니다. 따라서 (간결하게) 아무것도 아닌 것에 의존 할 수 없습니다.

JVM이 객체를 구현하고 적절하게 보이는대로 자유롭게 움직일 수 있기 때문에 변수의 메모리 주소를 얻는 것은 의미가 없습니다 (가비지 수집 중에 객체가 움직일 수 있음).

Integer.toBinaryString () 은 이진 형식의 정수를 제공합니다.


33
또 다른 흥미로운 점은 ID 해시 코드 가 고유하지 않다는 것입니다. 예를 들어 64 비트 JVM에는 2 ^ 32 ID 해시 코드가 있지만 2 ^ 64 메모리 주소가 있습니다.
Alex Jasmin

11
실제로 신원 해시 코드 는 변경할 수 없으며 , 그렇지 않으면 hashCode () 계약이 위반됩니다.
매트 맥 헨리

1
객체가 동일한 객체 대신 동일한 객체를 가리킬 때 로그를 결정하기 위해 로깅 / 디버깅에 이것을 사용하고 있습니다. 이러한 목적을 위해 identityHashcode의미가없는 것은 아닙니다. :)
썰매

@BrianAgnew : 알고 싶습니다-> 왜 두 객체에 동일한 해시 코드가 있습니까? c 또는 c ++에서 모든 변수 또는 객체의 메모리 위치가 다르므로 혼란 스럽습니다. 그런 다음 java에서 동일한 hashCode로 두 객체를 식별하거나 구별하는 방법.
Ved Prakash

1
@VedPrakash 객체 해시 코드를 사용하면 객체를 해시 모음에 저장할 수 있습니다. 두 개의 서로 다른 객체를 구별하려면 참조 평등을 사용하면됩니다.
Brian Agnew

36

그것은 가능합니다 sun.misc.Unsafe: @ Peter Lawrey의 훌륭한 답변을보십시오-> 참조 주소를 얻는 방법이 있습니까?

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

이 테스트를 설정했습니다.

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

출력은 다음과 같습니다.

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

결론 :

  • 해시 코드! = 주소
  • toString = class @ HEX (해시 코드)

13

이것이 Object의 "toString ()"구현 결과입니다. 클래스가 toString ()을 재정의하면 완전히 다른 것을 인쇄합니다.


6

입니다 메모리 주소가 아닌 이것은 클래스 명에 @ 해시 코드

어디

classname = 정규화 된 이름 또는 절대 이름 (예 : 패키지 이름 뒤에 클래스 이름)

hashcode = 16 진수 형식 (System.identityHashCode (obj) 또는 obj.hashCode ()는 10 진수 형식의 해시 코드를 제공합니다)


4

Sunil이 말했듯 이 이것은 메모리 주소 가 아니며 해시 코드 일뿐입니다.

동일한 @ 컨텐츠를 얻으려면 다음을 수행하십시오.

해당 클래스에서 hashCode가 재정의되지 않은 경우 :

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

hashCode가 재정의되면 다음을 사용하여 원래 값을 얻습니다.

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

hashCode ()를 재정의하지 않으면 해시를 계산하는 데 메모리 주소가 사용되므로 메모리 주소와 혼동되는 경우가 많습니다.


1

당신이 얻는 것은 Object 클래스의 toString () 메소드 또는 더 정확하게 uzay95가 지적한 identityHashCode ()의 결과입니다.

"새 키워드로 java에서 객체를 만들면 OS에서 메모리 주소를 얻습니다."

Java에서 수행하는 모든 작업이 Java Virtual Machine에 의해 처리된다는 것을 인식해야합니다. 이 정보를 제공하는 것은 JVM입니다. 호스트 운영 체제의 RAM에서 실제로 발생하는 것은 전적으로 JRE의 구현에 달려 있습니다.



0

당신은 같은 클래스에서 개체를 만들 때 자바에서 Person p = new Person();, p사실의 종류를 가리키는 메모리 위치의 주소입니다 Person.

statemenet을 사용하여 인쇄 p하면 주소가 표시됩니다. new키 워드에 포함 된 모든 인스턴스 변수 및 방법 함유하는 새로운 메모리 위치하게 class Person하고 p해당 메모리 위치를 가리키는 참조 변수이다.


그림 a1과 a2는 서로 다른 두 개의 메모리 주소이므로 두 개의 다른 값을 얻는 이유가 있습니다.
Panduka Wedisinghe
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.