JVM-JAVA对象的访问

JAVA中对象的访问

    JAVA是面向对象的语言,那么在JAVA虚拟机中,存在非常多的对象,对象访问是无处不在的。即时是最简单的访问,也会涉及到JAVA栈、JAVA堆、方法区这三个非常重要的内存区域之间的关联关系。

 

比如:

    Object obj = new Object();

 

    其中,“Object obj”这部分语义作为一个reference类型数据出现,将存储到JAVA栈的本地变量表中。new Object()将生成一个实体对象,存储在JAVA堆中,包含了Object类型的所有实例数据值(对象中各个字段的数据)的结构化内存,根据具体类型以及虚拟机实现的对象内存布局的不同,这块内存的长度是不固定的。另外,在JAVA堆中还必须包含能查找到此对象类型数据(如对象类型、父类、实现接口、方法等)的地址信息,这些类型数据存储在方法区中。

 

    由于reference类型在JAVA虚拟机规范里面只规定了一个指向对象的引用,并没有定义这个引用该通过哪种方式去定位,以及访问到JAVA堆中的对象的具体位置,因此不同虚拟机实现的对象访问方式会有所不同,主流的访问方式有两种:句柄直接指针

  • 句柄

    JAVA堆中将会划分出来一块内存作为句柄池,reference中就是存储了对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息。

    使用句柄访问的最大好处是reference中存储的是稳定的句柄地址,在对象被移动时,只会改变句柄中的实例数据指针,而reference本身不需要被修改。


 

  • 直接指针

    相比较句柄的访问方式,JAVA堆中不会单独划分内存,reference中直接存储了对象地址,而对象中包含了对象类型数据的地址信息。

    使用直接指针的最大好处就是速度更快,节省了一次指针定位需要的时间开销,由于JAVA对象访问十分频繁,这类开销积小成多后也是一项非常可观的执行成本。Sun HotSpot虚拟机使用的就是这种访问方式。


 

一个实体类,名为Stu:

public class Stu extends Object{
  private String name;
  private int age;
  public Stu(String name,String age){
    this.name = name;
    this.age = age;
  }
  public String getName(){
    return this.name;
  }
  ...
}

创建Stu对象:

    Stu kevin = new Stu(“kevin”,15); 

 

这样根据上文解释如下:

kevin作为一个reference类型的变量存储在本地变量表中,在hot spot虚拟机中,存储的是(kevin=)具体对象的直接地址;new Stu(“kevin”,15)就是实例化了一个对象,JAVA堆中Stu实体类的所有的字段信息,比如name=”kevin”,age=15。此时,JAVA堆中还存储了Stu对象的类型数据的地址信息,通过这个地址在方法区中可以查找对象的类型、父类、实现的接口、方法等信息。

猜你喜欢

转载自blog.csdn.net/u012909091/article/details/50451521