为啥要采用地址对其的机制?
如果某块内存地址的边界不是2的倍数,会多消耗1个CPU周期来读取。为了减少这一个CPU周期,所以现代操作系统都采取了内存地址对齐的机制。
为什么呢?
因为一个CPU周期只能处理2的幂指数,所以非2的幂指数倍的内存区域就会多出那么一块,这么一块根本不到一个CPU周期能处理的范围,还必须浪费一个CPU周期,麻烦。
单单从内存地址是无法看出某变量占用多少个字节的,本书有错。
计算字节数的方法是16进制内存地址之差的绝对值转换成10进制就OK了。
书中说对于64位的系统而言,应用的内存地址前边都是0.
其实是这样的,2的64次方是非常大的,应用的内存地址是先占据低地址空间再慢慢往高处增长,低地址空间左侧高位全是0,应用的数量还用不着那么多地址,所以终止地址还打不到高位非0的内存地址那里,这就是作者说的话的完美解释。
转换成俗话就是低内存地址都没用完,高内存地址根本就用不着。
标记指针不仅仅是指针。
它除了指针作用外,还能保存额外的信息,这全是由于那么多内存用不完导致的,就是反正我内存多给你点内存干别的也无所谓。
书中举了的例子。
打印的结果中最后两位0x2表示的就是指针的标记(tag),一开始的是0xb,它俩之间的数字转换成10进制就是该nsnumber的值了。
所以可以看出标记指针不再使用地址空间来表示具体的值了,而是单单使用内存地址值就行了,所以再也不用到堆上去取值了。
不过,这是在内存地址空间足够大的前提下。
假如说某个值过于大,操作系统还是会到堆上去分配空间的。
这个时候还是会以内存地址对齐的方式来分配空间的,所以后四位都是0,转换成16进制的形式就是0。
所以区分是否是标记指针可以通过地址最后一位是否是0来判断。
64位和32位环境对于ISA指针的不同处理
每个对象都有一个ISA指针。
在32位环境下,对象引用计数的每次变化都是先锁定外部表,操作完成后再解锁,锁定解锁非常浪费时间。
而在64位环境下,ISA指针除了作为ISA指针的公用之外,还能用来存储对象的引用计数,并且这个操作天然就是原子性的。
在64位环境下原本32位就足够的ISA指针被分配了33bit,用来表示引用计数的位数达到了19bit。
只有当引用计数所需位数超过19bit才会转换为64bit的处理模式。