对象的内存布局
- 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)、对齐填充(Padding)。
- 对象头包括两部分信息:
- 第一部分用于存储对象的自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID等。
- 第二部分是类型指针,即对象指向它的类元数据(存放在方法区)的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。
- 对象头包括两部分信息:
- 实例数据部分:是对象真正存储的有效信息,也是在程序代码中所定义的各种类型的字段内容。无论是从父类继承下来的,还是在子类中定义的,都需要记录起来。
- 对齐填充:略。
对象的访问定位
概述:建立对象是为了使用对象,我们的Java程序需要通过栈上的reference数据来操作堆上的具体对象。目前主流的访问方式有使用句柄和直接指针两种。
- 直接指针访问方式的最大好处就是速度更快,它节省了一次指针定位的时间开销,由于对象的访问在Java中非常频繁,HotSpot采用的便是这种方式。
- 下图即为Java利用直接指针访问对象:
实例分析###
public class Dog{
private int age;
public Dog() {
}
public Dog(int age){
this.age = age;
}
public int getAge() {
return age;
}
public static void main(String[] args) {
Dog dog = new Dog();
...
}
}
- 内存分配图如下
- 重点内容说明
- 构造方法or实例方法:需要将this指针(即对象地址),传递进方法内,才可以访问属性,即才知道访问哪一个对象的属性。这才是方法内为什么会隐含一个this指针。
- 静态方法:由于静态方法内不允许含有对象属性,因此应该不含有this指针。这和构造方法是不同的,我也一直对《Thinking in Java》所提到的:“构造方法应该隐含是静态的”,持有疑问态度,虽然某些角度看,两者有相似的地方,但是从大部分方面看都是不同的。
- 调用构造方法不一定会创建对象,但是调用构造方法可以初始化对象。最强有力的证明就是new子类对象的时候肯定会调用父类对象的构造方法,但是并不会创建父类对象。虚拟机只有接收到new指令的时候,才会真正的去创建父类对象。
好了,最后打住收工,啊弥陀否!!!
网友评论