Java虚拟机规范状态
引用类型有三种:类类型,数组类型和接口类型。 它们的值分别引用 动态创建的类实例,数组或实现接口的类实例或数组。
并澄清
类型 引用的 值可以认为 是指向对象的指针 。
所以变量
myAnimal在
Animal myAnimal = new Animal();
正在将指向
Animal对象的指针存储在堆上。
你问
内存地址值看起来如何?
内存地址通常只是一个数值,它是对进程分配的内存的偏移量。当进程读取该值时,它可以直接寻址该位置并对其进行读取或写入(将其视为数组中的偏移量索引)。
对象本身不仅仅是其地址。实际上,随着垃圾回收器移动对象,其地址在JVM进程的整个生命周期中可能会多次更改。
但是,JVMS并未指定对象的内部结构。
Java虚拟机不要求对象具有任何特定的内部结构。
在Oracle对Java虚拟机的某些实现中,对类实例的引用是指向本身是一对指针的句柄的指针:一个指向包含对象方法的表的指针,以及指向表示对象的Class对象的指针对象的类型,另一个分配给从堆为对象数据分配的内存。
这没有太大帮助,但是我们可以假设为对象数据分配的内存必须足够大以包含所有对象的字段,并且需要快速访问数据。在恒定时间内,而不是与数据量成正比。典型的解决方案是再次使用偏移量。以这个班为例
class Animal { private String name; private byte height;}
该字段
name是type
String,是引用类型,我们基本上只知道存储一个指针。如果我们假设JVM仅需要32位来存储指针,那么我们知道该字段仅需要32位。
该字段
height的类型
byte为,仅指定为8位。
因此,每个
Person对象实际上只需要
32+85位字节的数据即可。JVM很可能会为其内部组织分配更多的资源,但让我们简化为这5个字节。在您的示例中,JVM将为分配前4个字节,为分配
name下一个字节
age。就像是
0 8 16 24 32 40 +--------+--------+--------+--------+--------+ | name | height |
你问
是一个地址还是多个地址值?如果只有一个,myAnimal如何访问动物对象的所有对象字段,例如myAnimal.name,myAnimal.height,…?
myAnimal仅包含一个地址,但类似
myAnimal.height
可以认为
height是从内存中读取1字节(因为我们知道是字节类型),该地址是通过将存入的值加4(因为的数据位置
height需要减去所需的4个字节
name)而确定的
myAnimal。
考虑
myAnimal存储指向的内存地址的指针,该指针的
12初始化是
name指向内存地址处的String
1345且
height值为6。在内存中,看起来像
myAnimal|vHeap: ...12.......13.......14.......15.......16.......17Object offsets: ....0 1 2 3 4 5 ....+--------+--------+--------+--------+--------+ | 1345 | 6 |
要读取
myAnimal.height,JVM将计算
12 + 4 =16并读取该
6偏移量处的字节()。要为分配一个新值
myAnimal.name,JVM将计算
12 +0并写入4个字节(代表一些新的指针值),并覆盖
1345。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)