Địa chỉ bộ nhớ của các biến trong Java


139

Hãy nhìn vào bức tranh dưới đây. Khi chúng ta tạo một đối tượng trong java bằng newtừ khóa, chúng ta sẽ nhận được một địa chỉ bộ nhớ từ HĐH.

Khi chúng ta viết, out.println(objName)chúng ta có thể thấy một chuỗi "đặc biệt" là đầu ra. Câu hỏi của tôi là:

  1. Đầu ra này là gì?
  2. Nếu đó là địa chỉ bộ nhớ do OS cung cấp cho chúng tôi:

    a) Làm thế nào tôi có thể chuyển đổi chuỗi này thành nhị phân?

    b) Làm thế nào tôi có thể nhận được một địa chỉ biến số nguyên?

văn bản thay thế


5
Tôi không bỏ phiếu vì câu hỏi đủ rõ ràng, chỉ là một gợi ý mà bạn nên đưa ra trong văn bản để mọi người có thể tìm kiếm nó
phunehehe

2
Sử dụng sun.misc.Unsafe có thể lấy địa chỉ của một đối tượng java. Để biết danh sách chương trình, hãy tham khảo: javapapers.com/core-java/address-of-a-java-object
Joseph Kulandai

giá trị nhọn là biểu diễn thập lục phân của mã băm của đối tượng a1 & a2
Naveen

Câu trả lời:


166

Đó là tên lớp và System.identityHashCode () được phân tách bằng ký tự '@'. Những gì mã băm nhận dạng đại diện là cụ thể thực hiện. Nó thường là địa chỉ bộ nhớ ban đầu của đối tượng, nhưng đối tượng có thể được di chuyển trong bộ nhớ bởi VM theo thời gian. Vì vậy (một thời gian ngắn) bạn không thể dựa vào nó là bất cứ điều gì.

Lấy địa chỉ bộ nhớ của các biến là vô nghĩa trong Java, vì JVM có quyền tự do triển khai các đối tượng và di chuyển chúng khi nó có vẻ phù hợp (các đối tượng của bạn có thể / sẽ di chuyển xung quanh trong quá trình thu gom rác, v.v.)

Integer.toBinaryString () sẽ cung cấp cho bạn một số nguyên ở dạng nhị phân.


33
Một điểm thú vị khác là mã băm nhận dạng không được đảm bảo là duy nhất. Ví dụ, trên JVM 64 bit, có 2 ^ 32 mã băm nhận dạng nhưng 2 ^ 64 địa chỉ bộ nhớ .
Alex Jasmin

11
Trên thực tế, mã băm danh tính không thể thay đổi , nếu không hợp đồng của hashCode () sẽ bị vi phạm.
Matt McHenry

1
Tôi đang sử dụng điều này để ghi nhật ký / gỡ lỗi để xác định nhật ký khi các đối tượng đang trỏ đến cùng một đối tượng thay vì các đối tượng tương đương. Đối với những mục đích identityHashcodenày không phải là vô nghĩa, nó chỉ không thể đánh lừa được. :)
Sled

@BrianAgnew: Tôi muốn biết -> Tại sao hai đối tượng có cùng mã băm. Tôi bối rối vì tôi đã học trong c hoặc c ++ mỗi biến hoặc đối tượng có vị trí bộ nhớ khác nhau. Sau đó, trong java Làm thế nào có thể xác định hoặc phân biệt hai đối tượng có cùng mã băm.
Ved Prakash

1
@VedPrakash mã băm đối tượng cho phép các đối tượng được lưu trữ trong các bộ sưu tập băm. Nếu bạn muốn phân biệt hai đối tượng khác nhau, bạn chỉ cần sử dụng đẳng thức tham chiếu
Brian Agnew

36

Có thể sử dụng sun.misc.Unsafe: xem câu trả lời tuyệt vời này từ @Peter Lawrey -> Có cách nào để có được địa chỉ tham khảo không?

Sử dụng mã của nó cho 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();
}

Tôi thiết lập thử nghiệm này:

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

Đây là đầu ra:

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

Phần kết luận :

  • mã băm! = địa chỉ
  • toString = class @ HEX (mã băm)

13

Đó là đầu ra của việc thực hiện "toString ()" của Object. Nếu lớp của bạn ghi đè lênString (), nó sẽ in thứ gì đó hoàn toàn khác.


6

Đây không phảiđịa chỉ bộ nhớ Đây là classname @ hashcode

Ở đâu

classname = tên đủ điều kiện hoặc tên tuyệt đối (nghĩa là tên gói theo sau là tên lớp)

hashcode = định dạng thập lục phân (System.identityHashCode (obj) hoặc obj.hashCode () sẽ cung cấp cho bạn mã băm ở định dạng thập phân)


4

Giống như Sunil đã nói, đây không phải là địa chỉ bộ nhớ . Đây chỉ là băm

Để có cùng nội dung @, bạn có thể:

Nếu hashCode không bị ghi đè trong lớp đó:

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

Nếu hashCode bị ghi đè, bạn sẽ nhận được giá trị ban đầu với:

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

Điều này thường bị nhầm lẫn với địa chỉ bộ nhớ vì nếu bạn không ghi đè hashCode (), địa chỉ bộ nhớ được sử dụng để tính toán hàm băm.


1

Những gì bạn đang nhận là kết quả của phương thức toString () của lớp Object hoặc chính xác hơn là nhận dạngHashCode () như uzay95 đã chỉ ra.

"Khi chúng tôi tạo một đối tượng trong java với từ khóa mới, chúng tôi sẽ nhận được một địa chỉ bộ nhớ từ HĐH."

Điều quan trọng là phải nhận ra rằng mọi thứ bạn làm trong Java đều được xử lý bởi Máy ảo Java. Đó là JVM đang cung cấp thông tin này. Những gì thực sự xảy ra trong RAM của hệ điều hành máy chủ phụ thuộc hoàn toàn vào việc thực hiện JRE.



0

Trong Java khi bạn tạo một đối tượng từ một lớp như thế Person p = new Person();, pthực sự là một địa chỉ của một vị trí bộ nhớ đang trỏ đến một loại Person.

Khi sử dụng một stHRenet để in, pbạn sẽ thấy một địa chỉ. Từ newkhóa tạo một vị trí bộ nhớ mới chứa tất cả các biến và phương thức được bao gồm trong đó class Personplà biến tham chiếu trỏ đến vị trí bộ nhớ đó.


trong ảnh của bạn a1 và a2 là hai địa chỉ bộ nhớ khác nhau. Đó là lý do đằng sau việc nhận hai giá trị khác nhau.
Panduka Wedisinghe
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.