How can a single reference variable access to all object fields?

后端 未结 4 1790
一生所求
一生所求 2021-01-13 17:22
Animal myAnimal = new Animal();

I have this code above. As far as I know, it will do these things :

  1. An animal object will be created
4条回答
  •  梦毁少年i
    2021-01-13 17:38

    The Java Virtual Machine Specification states

    There are three kinds of reference types: class types, array types, and interface types. Their values are references to dynamically created class instances, arrays, or class instances or arrays that implement interfaces, respectively.

    and clarifies

    Values of type reference can be thought of as pointers to objects.

    So the variable myAnimal in

    Animal myAnimal = new Animal();
    

    is storing a pointer to the Animal object on the heap.

    You ask

    How does the memory address value look like?

    A memory address is typically just a numerical value that's an offset into the process' allocated memory. When a process reads that value, it can directly address that location and read from or write to it (think of it as an offset index in an array).

    The object itself is more than just its address. In fact, its address can change multiple times over the lifetime of the JVM process as the garbage collector moves objects around.

    However, the JVMS does not specify the internal structure of an object.

    The Java Virtual Machine does not mandate any particular internal structure for objects.

    In some of Oracle’s implementations of the Java Virtual Machine, a reference to a class instance is a pointer to a handle that is itself a pair of pointers: one to a table containing the methods of the object and a pointer to the Class object that represents the type of the object, and the other to the memory allocated from the heap for the object data.

    This doesn't help greatly, but we can assume that the memory allocated for the object data has to be large enough to contain all the object's fields and the data needs to be accessible quickly, ie. in constant time, as opposed to proportionally to the amount of data. The typical solution is to again use offsets. Take this class for example

    class Animal {
        private String name;
        private byte height;
    }
    

    The field name is of type String, a reference type, which we know essentially just stores a pointer. If we assume our JVM only needs 32 bits to store a pointer, we know we only need 32 bits for this field.

    The field height is of type byte, which is specified to only need 8 bits.

    So each Person object really only needs 32+8 bits, 5 bytes for its data. The JVM will most likely allocate more than that for its internal organization, but let's simplify to just those 5 bytes. In your example, the JVM will allocate the first 4 bytes for the name and the next byte for the age. Something like

     0        8       16       24       32       40
     +--------+--------+--------+--------+--------+
     |               name                | height |
    

    You ask

    Is that one address or numerous address value? If only one, how can myAnimal have accesses to all object fields of Animal object like myAnimal.name, myAnimal.height,...?

    myAnimal holds only one address, but an expression like

    myAnimal.height
    

    can be thought of as reading 1 byte (because we know height is of type byte) from memory at the address determined by adding 4 (because the location of the data for height is offset by the 4 bytes needed for name) to the value stored in myAnimal.

    Consider myAnimal storing a pointer to a memory address of 12, initialized with a name pointing to a String at memory address 1345 and a height value of 6. In memory, that could look like

                       myAnimal
                          |
                          v
    Heap:             ...12.......13.......14.......15.......16.......17
    Object offsets:   ....0        1        2        3        4        5
                      ....+--------+--------+--------+--------+--------+ 
                          |               1345                |    6   | 
    

    To read myAnimal.height, the JVM would calculate 12 + 4 = 16 and read the byte (6) at that offset. To assign a new value to myAnimal.name, the JVM would calculate 12 + 0, and write 4 bytes representing some the new pointer value, overwriting the 1345.

提交回复
热议问题