• JVM栈帧-局部变量表中引用类型的理解


      《深入理解Java虚拟机》中在描述JVM栈帧的局部变量表时,有这样一段话:

      局部变量表存放了编译期可知的各种Java虚拟机基本数据类型(boolean、bytecharshortintfloatlongdouble)、对象引用(reference类型,它并不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或者其他与此对象相关的位置)和returnAddress 类型(指向了一条字节码指令的地址)。

      我们在这里不讨论基本类型和returnAddress。单独说一说对象引用的理解。--它并不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或者其他与此对象相关的位置。

    ———————————————————————————————————————————

      里面的描述令我很迷惑,这个“句柄”的概念其实也是高频地出现在了Thinking In Java这本经典中,那么在物理内存中,这个句柄到底是什么呢?另外,这里的对象引用难道不是在堆内存中真实对象的地址么,为什么除了指针之外还有别的可能呢?

      在Google搜索了一通之后,发现了一个解释,结合自己的理解,这里记录一下。

    ———————————————————————————————————————————

      首先,如果这个对象引用就是堆内存中该对象的地址,那么很好理解。接下来重点说句柄和相关的位置。

      句柄是一个唯一的整数,作为对象的身份id,区分不同的对象,和同类中的不同实例。程序可以通过句柄访问对象的部分信息。句柄不代表对象的真实内存地址。

      那么从这里我们可以判断,句柄不是堆内存中的地址,而且通过这个整数,程序可以访问到对象的部分信息。那么这个整数真实访问的是什么呢?其实是一组映射,也就是说,句柄访问了该映射,而这个映射中存有堆内存里真实对象的地址。这里举一个MySQL存储数据的例子来进行类比。比如有个订单表,表里有一个字段userId,存储了系统中注册用户的信息。那么我们拿到一个订单id,首先是去找到订单的这一行数据,而这行数据的userId,找到User表,才能真正查询到用户的信息。这样一来,这个句柄的概念,就比较好理解了,而文中所说的“或者其它与此对象相关的位置”也就找到了解释,不管这里所说的相关位置是什么,肯定是最终能够找到堆内存中具体的对象的,所以作者这样的描述是准确的。

      另外,句柄能够访问到对象的部分信息,也就不难理解了。我们还是拿订单表和用户表的例子来说明,所谓的部分信息,也就是在订单表里,能够找到除了user真实地址之外的信息,比如我们在订单表里不仅存放了userId,也存放了这个用户的类型(App用户,PC用户...),便于我们查询。那么所谓的部分信息,应该是指除了真实的对象地址,也放入了这个对象其他信息。

      真实情况是,一部分是直接地址,另一部分是存储了句柄池的地址,而这个指向的句柄池放了对象的真实地址(堆内存中),也放入了对象类型(class)信息的地址(方法区中)。

    ———————————————————————————————————————————

      理解了上面的这句话,我们要问两个为什么:1.为什么这个对象引用可以有这么多种可能?2.直接使用对象的地址不是很好吗,Java为什么会有句柄这个东西?

      解释:

      1.JVM虚拟机规范中,只要求根据对象引用的这个值,最终能够找到对象的内存地址,但是没有规定必须使用哪种方式。它只定义了一个接口,不同的JVM可以有不同的实现方式。可以使用对象的内存地址,也可以使用句柄这种通过映射找到内存地址的方式,也可以是别的方式。这里也能够说明为什么原文里的描述还有“或者其他与此对象相关的位置”的说法。

      2.内存地址是很方便的,而且节省了一次寻址的消耗。但是我们想一想,这个地方原文描述的是栈帧中的局部变量表,在多线程的环境下,不同的线程里处理着不同的栈帧,而这些栈帧随着方法执行的开始或者结束在不停地入栈和出栈。假设这个时候,发生了一次垃圾回收,对象在内存中的地址发生了变化,那么JVM就必须到这个动态的环境中,将所有相关的内存地址修改过来,这可是一个很复杂且容易出错的过程......如果用一个映射表,在栈帧中的对象引用拿着这个固定的数字,那么当内存地址发生变化时,JVM只需要修改这个映射表中数字对应的对象地址,这可比第一种方案简单多了!

    ———————————————————————————————————————————

      这里只是记录自己的理解,甚至是一些猜测。所以,如果你有不同的理解或者你知道更为准确的过程信息,欢迎留言讨论。

  • 相关阅读:
    laravel 查询
    好友数量
    laravel 更新
    laravel 多对多关联 attach detach sync
    laravel zh-CN
    laravel 框架后台主菜单接口
    Visual Studio 2012 Update 3
    IIS7 禁止目录运行脚本
    [驱动力]读书笔记
    [Python Essential Reference, Fourth Edition (2009)]读书笔记
  • 原文地址:https://www.cnblogs.com/bruceChan0018/p/15032703.html
Copyright © 2020-2023  润新知