JVM栈帧-局部变量表中引用类型的理解
2021/7/19 23:06:03
本文主要是介绍JVM栈帧-局部变量表中引用类型的理解,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
《深入理解Java虚拟机》中在描述JVM栈帧的局部变量表时,有这样一段话:
局部变量表存放了编译期可知的各种Java虚拟机基本数据类型(boolean、byte、char、short、int、 float、long、double)、对象引用(reference类型,它并不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或者其他与此对象相关的位置)和returnAddress 类型(指向了一条字节码指令的地址)。
我们在这里不讨论基本类型和returnAddress。单独说一说对象引用的理解。--它并不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或者其他与此对象相关的位置。
———————————————————————————————————————————
里面的描述令我很迷惑,这个“句柄”的概念其实也是高频地出现在了Thinking In Java这本经典中,那么在物理内存中,这个句柄到底是什么呢?另外,这里的对象引用难道不是在堆内存中真实对象的地址么,为什么除了指针之外还有别的可能呢?
在Google搜索了一通之后,发现了一个解释,结合自己的理解,这里记录一下。
———————————————————————————————————————————
首先,如果这个对象引用就是堆内存中该对象的地址,那么很好理解。接下来重点说句柄和相关的位置。
句柄是一个唯一的整数,作为对象的身份id,区分不同的对象,和同类中的不同实例。程序可以通过句柄访问对象的部分信息。句柄不代表对象的真实内存地址。
那么从这里我们可以判断,句柄不是堆内存中的地址,而且通过这个整数,程序可以访问到对象的部分信息。那么这个整数真实访问的是什么呢?其实是一组映射,也就是说,句柄访问了该映射,而这个映射中存有堆内存里真实对象的地址。这里举一个MySQL存储数据的例子来进行类比。比如有个订单表,表里有一个字段userId,存储了系统中注册用户的信息。那么我们拿到一个订单id,首先是去找到订单的这一行数据,而这行数据的userId,找到User表,才能真正查询到用户的信息。这样一来,这个句柄的概念,就比较好理解了,而文中所说的“或者其它与此对象相关的位置”也就找到了解释,不管这里所说的相关位置是什么,肯定是最终能够找到堆内存中具体的对象的,所以作者这样的描述是准确的。
另外,句柄能够访问到对象的部分信息,也就不难理解了。我们还是拿订单表和用户表的例子来说明,所谓的部分信息,也就是在订单表里,能够找到除了user真实地址之外的一些属性信息,比如我们在订单表里不仅存放了userId,也存放了这个用户的手机号码,便于我们查询。那么所谓的部分信息,应该是指除了真实的对象地址,也放入了这个对象其他的一些信息。
———————————————————————————————————————————
理解了上面的这句话,我们要问两个为什么:1.为什么这个对象引用可以有这么多种可能?2.直接使用对象的地址不是很好吗,Java为什么会有句柄这个东西?
解释:
1.JVM虚拟机规范中,只要求根据对象引用的这个值,最终能够找到对象的内存地址,但是没有规定必须使用哪种方式。也就是说,它只定义了一个接口,不同的JVM可以有不同的实现方式,也就是说,可以使用对象的内存地址,也可以使用句柄这种通过映射找到内存地址的方式,也可以是别的方式。这里也能够说明为什么原文里的描述还有“或者其他与此对象相关的位置”的说法。
2.内存地址是很方便的,而且节省了一次寻址的消耗。但是我们想一想,这个地方原文描述的是栈帧中的局部变量表,在多线程的环境下,不同的线程里处理着不同的栈帧,而这些栈帧随着方法执行的开始或者结束在不停地入栈和出栈。假设这个时候,发生了一次垃圾回收,对象在内存中的地址发生了变化,那么JVM就必须到这个动态的环境中,将所有相关的内存地址修改过来,这可是一个很复杂且容易出错的过程......如果用一个映射表,在栈帧中的对象引用拿着这个固定的数字,那么当内存地址发生变化时,JVM只需要修改这个映射表中数字对应的对象地址,这可比第一种方案简单多了!
———————————————————————————————————————————
这里只是记录自己的理解,甚至是一些猜测。所以,如果你有不同的理解或者你知道更为准确的过程信息,欢迎留言讨论。
这篇关于JVM栈帧-局部变量表中引用类型的理解的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-16Maven资料入门指南
- 2024-11-16Maven资料入门教程
- 2024-11-16MyBatis Plus资料:新手入门教程与实践指南
- 2024-11-16MyBatis-Plus资料入门教程:快速上手指南
- 2024-11-16Mybatis资料入门教程:新手必看指南
- 2024-11-16MyBatis资料详解:新手入门与初级实战指南
- 2024-11-16MyBatisPlus资料:初学者入门指南与实用教程
- 2024-11-16MybatisPlus资料详解:初学者入门指南
- 2024-11-16MyBatisX资料:新手入门与初级教程
- 2024-11-16RESTful接口资料详解:新手入门指南