Java 单个引用变量如何访问所有对象字段?

Java 单个引用变量如何访问所有对象字段?,java,jvm,Java,Jvm,我有上面的代码。据我所知,它会做这些事情: 将在堆内存上创建动物对象 对该对象的引用将传递给引用变量“myAnimal” 换句话说,“myAnimal”变量保存堆上“Animal”对象的内存地址 我不明白的是 内存地址值是什么样子的 这是一个地址还是多个地址值?如果只有一个,myAnimal如何访问动物对象的所有对象字段,如myAnimal.name、myAnimal.height等 有人能解释一下吗?提前感谢。这是一个过于简单的说法: 它只是一个代表某个地址位置的数字;这个数字有多大取决于计算

我有上面的代码。据我所知,它会做这些事情:

  • 将在堆内存上创建动物对象
  • 对该对象的引用将传递给引用变量“myAnimal” 换句话说,“myAnimal”变量保存堆上“Animal”对象的内存地址
  • 我不明白的是

  • 内存地址值是什么样子的
  • 这是一个地址还是多个地址值?如果只有一个,myAnimal如何访问动物对象的所有对象字段,如myAnimal.name、myAnimal.height等

  • 有人能解释一下吗?提前感谢。

    这是一个过于简单的说法:

  • 它只是一个代表某个地址位置的数字;这个数字有多大取决于计算机的体系结构(32位或64位)

  • 它是一个地址值;它是内存中对象表示开始的位置的地址位置


  • 你可以把它和你家的地址相比较。它有一个地址。您家中的所有房间(字段)都有不同的位置,但您必须从前门进入(“开始”位置)。房间位置相对于您的前门。我承认这个例子有点做作,但你明白了…

    地址只是
    长的
    数字,用来表示对象的内存位置。它们取决于机器的钻头。它在64位机器上为64位长,在32位机器上为32位长

    内存地址值是什么样子的

    如果您真的很想在控制台中看到这些大数字,那么您实际上可以探索

    从给定内存地址获取本机指针。如果地址是 零,或不指向从#allocateMemory获得的块,结果未定义

    如果本机指针的宽度小于64位,则将其扩展为 Java long的无符号数字。指针可以由任何 给定字节偏移量,只需将该偏移量(作为简单整数)添加到 表示指针的长字符。实际读取的字节数 从目标地址可以通过咨询#addressSize确定


    这是一个地址还是多个地址值?如果只有一个,myAnimal如何访问动物对象的所有对象字段,如myAnimal.name、myAnimal.height等

    嗯,它应该是顶层的一个,地址位置可能包含其他人的地址位置(我不太确定)


    我还没有在我的机器上真正尝试过运行它。

    当一个对象被创建时,java不会与引用变量共享它的
    实际内存地址
    ,而不是java为你的
    对象
    创建一个
    索引号
    ,它会被传递到该对象的
    引用变量
    。因此,您可以借助该
    索引号
    访问您的对象。此外,您的对象持有其
    子对象的
    引用
    ,并帮助您访问它们。

    Java虚拟机规范

    引用类型有三种:类类型、数组类型、, 和接口类型它们的值是动态引用的 创建的类实例、数组或类实例或数组 分别实现接口

    类型引用的值可以被认为是指向对象的指针

    因此变量
    myAnimal
    in

    public native long getAddress(long address)
    
    正在堆上存储指向
    动物
    对象的指针

    你问

    内存地址值是什么样子的

    内存地址通常只是一个数值,它是进程分配内存的偏移量。当进程读取该值时,它可以直接寻址该位置并对其进行读取或写入(将其视为数组中的偏移索引)

    对象本身不仅仅是它的地址。事实上,当垃圾收集器移动对象时,它的地址可以在JVM进程的生命周期内多次更改

    但是,对象的内部结构

    Java虚拟机不要求任何特定的内部 对象的结构

    在Oracle的一些Java虚拟机实现中 对类实例的引用是指向其自身的句柄的指针 一对指针:一个指向包含 对象和指向表示对象类型的类对象的指针 对象,另一个为从堆中分配的内存 对象数据

    这没有多大帮助,但我们可以假设为对象数据分配的内存必须足够大,以包含所有对象的字段,并且数据需要快速访问,即在恒定时间内,而不是与数据量成比例地访问。典型的解决方案是再次使用偏移。以这门课为例

    Animal myAnimal = new Animal();
    
    字段
    name
    的类型为
    String
    ,这是一种引用类型,我们知道它基本上只存储一个指针。如果我们假设JVM只需要32位来存储指针,那么我们知道这个字段只需要32位

    字段
    高度
    的类型为
    字节
    ,指定为仅需要8位

    因此,每个
    Person
    对象实际上只需要
    32+8
    位,即5字节的数据。JVM很可能会为其内部组织分配更多的资源,但让我们简化为仅分配这5个字节。在您的示例中,JVM将为
    名称
    分配前4个字节,为
    年龄
    分配下一个字节。差不多

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

    这是一个地址还是多个地址值?如果只有一个,怎么可能 myAnimal可以访问动物对象的所有对象字段,如 我的动物。名字,myAni
    class Animal {
        private String name;
        private byte height;
    }
    
     0        8       16       24       32       40
     +--------+--------+--------+--------+--------+
     |               name                | height |
    
    myAnimal.height
    
                       myAnimal
                          |
                          v
    Heap:             ...12.......13.......14.......15.......16.......17
    Object offsets:   ....0        1        2        3        4        5
                      ....+--------+--------+--------+--------+--------+ 
                          |               1345                |    6   |