关于虚拟机中对象访问定位的两种方式的一些思考

前言

本文是在周志明老师经典作品《深入理解Java虚拟机》第二章第三节的基础上对句柄和直接指针两种对象访问方式的深入思考,有不准确的地方希望读者不吝赐教。

JVM中访问对象的两种方式

1.句柄

在这里难免要讨论一下所谓的“句柄”究竟是什么?虽然知道大部分读者应该是很熟悉这个概念的,但是本人在此之前只是对这个词耳熟,具体概念却不是很清楚,在这里详细介绍一下,既是和读者探讨,也是给自己作个记录。
句柄,句子的柄,我们想一下什么是柄?类比一下勺子,勺子柄的作用是让使用者能很轻松的抓住勺子进行使用,与之类似,句柄也可以看成是为了让使用者便于“抓取”这个“句子”而存在的东西。但实际上它对应的主体不是一般概念上的句子,而是“项目”。要探究句柄的本质就要追根溯源到Windows编程中而不是仅仅局限在某种语言或者虚拟机上了。
下面我用尽可能简洁明了的语言总结一下句柄究竟是为何物?
句柄是在Windows编程中用来标识对象或项目的一种标识符。从数据类型上看它是一组32位的无符号整数,从功能上看它可以看作是指针的“指针”,换言之,通过它我们可以找到目标对象的指针,从而间接操作数据。但是使用句柄又能避免一个问题,就是直接操作数据的问题,因为如果直接使用指针操作数据,那么我们实际上是在对象的物理地址上进行的操作,这样一来不管什么操作可以肆无忌惮的进行,无法控制,系统是不能容忍这种情况发生的,因此以句柄为“媒介”,既可以保留操作数据的能力,又规避了随意操作数据的恶意。通过句柄我们可以操作以下这几种对象(十大类):
(1)模块(module)
(2)任务(task)
(3)实例(instance)
(4)文件(file)
(5)菜单(menu)
(6)内存块(block of memory)
(7)控制(control)
(8)字体(font)
(9)资源(resource),包括图标(icon)、光标(cursor)、字符串(string)等
(10)GDI对象(GDI object),包括位图(bitmap)、画刷(brush)、元文件(metafile)、调色板(palette)、画笔(pen)、区域(region),以及设备描述表(device context).

与以上集中对象相对应的句柄类型有这么几种:
(1)HINSTANCE(实例句柄)
(2)HBITMAP(位图句柄)
(3)HDC(设备表述句柄)
(4)HICON(图标句柄)
(5)HANDLE(通用句柄)

其实,根据Winnt.h中的代码可以发现,HANDLE实际上就是一个无类型指针。
详见以下这篇文章:https://www.cnblogs.com/yellowyu/archive/2009/06/07/1497910.html
在Windows系统中,内存管理器经常会在内存中来回移动对象,一次满足程序的需要。对象被移动意味着他的地址变了,换句话说,对象的内存地址会随着应用程序的需要经常变动。为此,Windows系统专门为应用程序腾出一些内存地址用来等级各应用对象在内存中的地址变化,而这块内存地址是不变的。当对象的地址改变后,就会记录在这块专门的内存地址中,我们知道了这块专门记录地址的内存地址就可以间接来操作数据了,这块专门的内存就是句柄,所谓的专门内存的地址就是句柄地址。这个地址是在对象装载时由系统分配的,当系统卸载时又释放给系统。并且程序每次重新启动时,系统也不能保证分配给这个程序的句柄还是之前的那个句柄,而且绝大多数情况是不一样的。因此,句柄地址也不一定是每次使用都一样的,仅在同一次程序运行过程中句柄才是固定的。
在这里插入图片描述

句柄地址(相对稳定)——>记载的对象在内存中的地址——>对象在内存中的地址(不稳定)——>实际对象

JVM中句柄定位逻辑:
在这里插入图片描述

2.直接指针

指针对应着一个数据在内存中的地址,得到了指针就可以自由修改数据。
JVM中直接指针定位逻辑:
在这里插入图片描述

两种方式对比:
在这里插入图片描述
两种方式各有优劣,使用句柄访问的好处是在每次对象位置发生变动时只需要改变句柄中指向实例数据的指针,而指向对象类型数据的指针和对象引用指针reference都不需要修改,而使用直接指针访问,当对象发生移动时对象引用reference需要修改。但是使用直接指针访问方式少了一次指针定位的时间开销速度更快。

3.关于句柄的几个问题以及句柄和指针的关系详解:

3.1下面这两张图可以更直观的表现句柄和指针的关系:

在这里插入图片描述
在这里插入图片描述

3.2

(1).所谓“唯一”、“不变”是指在程序的一次运行中。如果本次运行完,关闭程序,再次启动程序运行,那么这次运行中,同一对象的句柄的值和上次运行时比较,一般是不一样的。

其实这理解起来也很自然,所谓“一把归一把,这把是这把,那把是那把,两者不相干”(“把”是形象的说法,就像打牌一样,这里指程序的一次运行)。

(2).句柄是对象生成时系统指定的,属性是只读的,程序员不能修改句柄

(3).不同的系统中,句柄的大小(字节数)是不同的,可以使用sizeof()来计算句柄的大小。

(4).通过句柄,程序员只能调用系统提供的服务(即API调用),不能像使用指针那样,做其它的事
一篇很棒的文章链接:https://www.cnblogs.com/zpcdbky/p/4652151.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值