局部变量表我在之前提过,实际上就是方法运行时的变量表,已经在.class文件中存在了,但是我们还需要扣一下细节,Java虚拟机并没有规定变量的大小
只是说一个slot(数据的最小单位),必须可以存放一个boolean,byte,char,short,int,float,reference(引用类型)
实际上就是指一个slot至少可以存放一个32位的数据,即,4字节,对于引用类型来说可能不一定小于等于32位
因为虚拟机实现不同,如果引用类型所包含的信息足够大,是有可能超过32位的,如,锁的信息,对象的年龄代信息,对象所指向的内存信息等等
但是基本上目前的虚拟机经过一系列的优化,基本都可以控制在4字节之内完成全部信息的存储,所以这篇文章默认引用类型的长度小于等于4字节
至少可以,说明是大于等于,如果有哪个jvm设置slot为64位,也是可行的(实际上没人这样干,毫无意义的浪费内存)
而除去上面的这几种类型,还有两种没有提到,即,long和double,Java虚拟机将他们规定为64位的数据,
但是这里有一个问题,long是64位的很好理解,但是为什么double也是64位呢?
从范围来看,明显double已经超过64位可以容纳的最大长度相当多,我翻了很多网上的博客和论坛
网上的博客和论坛大部分是说是因为double采用了特殊的数据存储,但是大多讲的不好,我在这里用自己的话说一下吧
查看Java Double(即,double包装类)源码,可知0x1.fffffffffffffP+1023是double的最大长度,那么为什么是这个值呢?
将他转换为二进制
可以把1.fffffffffffff看做二进制的1(请忽略那个点)—1111(即二进制对于16进制的f)—1111*12(f太多了,省略)
也就是说前面的1.fffffffffffff实际上在二进制中占4*13+1位,共53位,而1023转换为二进制数,即为11–1111—1111
即,10位数,加上前面的53位,共63位,补上一位符号位,即为64位,这就是为什么double是64位的原因,在Java中double实际上是将两个数据存放在double中了
这是double的数据模型
位置 | 意义 |
---|---|
1 | 符号位 |
2-54 | 精确数值 |
55-64 | 科学计数位 |
也就是说在doble中可靠数据最大只有17976931348623157即,2的53次方-1,同为浮点类型的float同理
而在jvm中通常把上文这两种64位的数据存放在两个slot中
也就是说,如果我们需要修改double中的数据,实际上需要操作两个slot,Java虚拟机明确规定了,如果字节码只操作其中一个slot,抛出异常
为了节省内存,slot是可以复用的,对于局部变量来说,如果一个变量离开了他的作用域范围,其他变量就可以复用这个slot
示例代码
public class Test {
public static void main(String[] args)