网站是先解析后备案吗,永久免费网站模板,做网站年入多少,企业网站登录入口官网1、JVM栈的数据存储 通过前面的学习#xff0c;我们知道#xff0c;将源代码编译成字节码文件后#xff0c;JVM会对其中的字节码指令解释执行#xff0c;在解释执行的过程中#xff0c;又利用到了栈区的操作数栈和局部变量表两部分。 而局部变量表又分为一个个的槽位…1、JVM栈的数据存储 通过前面的学习我们知道将源代码编译成字节码文件后JVM会对其中的字节码指令解释执行在解释执行的过程中又利用到了栈区的操作数栈和局部变量表两部分。 而局部变量表又分为一个个的槽位通常第0个槽位存放实例方法的this。而每个槽位的空间大小是根据不同虚拟机决定的
32位虚拟机32位4个字节。64位虚拟机64位8个字节。 在Java中有八大基本数据类型它们在堆中占用的字节数都是不同的如下表所示 其中内存占用最多的是long和double类型8个字节。 它们在局部变量表中需要占用两个槽位。如果这样说很多人会有疑问每个槽位的空间大小是根据不同虚拟机决定的如果是32位虚拟机每个槽位只有4个字节占用两个槽位是没有问题的。但是如果是64位虚拟机呢每个槽位有8个字节按理说一个槽位就可以放下了为什么还是需要占用两个槽位 原因在于Java语言的跨平台特性。局部变量表是在编译期间就确定下来的无法得知将来JVM会在何种环境下解释执行字节码指令。所以为了保证通用性统一按照64位虚拟机进行考虑。并且虽然long和double类型占用了两个槽位共16个字节实际上它的高8字节是没有被使用的。 栈中的数据要保存到堆上堆中加载到栈上需要如何实现 在编译成的字节码文件中所有占用了一个槽位的数据类型都是被当做了int执行(iconst)int默认占有4个字节也就是在栈上这些都默认占有了4个字节。 但是在堆上它们实际有的只占有了1个字节有的占有了2个字节。所以栈中的数据要保存在堆上需要进行截取堆中的数据加载到栈上则反之。 在进行过程分析之前首先要明白两个概念符号位和高低位
符号位符号位是在计算机中用来表示数值的正负的特殊位。通常情况下一个整数的符号位是用来表示该整数是正数还是负数的。在计算机中符号位通常是由整数类型的最高位最左侧的位来表示的其中 0 表示正数1 表示负数。例如在一个有符号的 8 位整数中如果最高位是 0则该整数被解释为正数如果最高位是 1则该整数被解释为负数。高低位通常是指在计算机中用于表示数字的二进制位的位置。在一个多字节的数据类型比如整数或者浮点数中位被分为高位和低位两部分。高位是数据中权值最高的位通常位于数据的最左侧。在有符号整数中高位通常用于表示符号位0 表示正数1 表示负数。在无符号整数中高位用于表示最大的数值。低位是数据中权值最低的位通常位于数据的最右侧。低位存储着数据的最小的权值。 堆中的数据加载到栈上时也要考虑符号位的问题。boolean和char类型没有符号位直接高位补0即可byte和short有符号位低位直接复制高位负则补1非负补0 栈中的数据要保存在堆上 需要将高位截取掉。而boolean类型只取低位的最后一位。
2、JVM对象在堆上的存储 对象在堆中的内存布局分为对象头和对象数据两部分对象头中又有标记字和类型指针。如果是数组对象类型对象头中额外保存了数组的容量。 其中标记字 的结构在64位和32位虚拟机中都不一样其中64位虚拟机又分为是否进行了指针压缩 这一块详见http://t.csdnimg.cn/8D7DI 我们也可以通过JoL jar包中提供的方法打印出这一块的信息 在打印出的信息中我们可以发现引用数据类型是排在最后的并且在类的定义中是long变量在前int变量在后。但是打印出的对象头信息中两者的顺序发生了交换原因在于每个属性的偏移量必须是字段长度的整数倍。在这个案例中假如long变量在前那么它的OFFSET和SIZE 就会变成12和8不满足整数倍的条件所以会做出调整。这就是内存对齐。 而内存对齐的主要目的是为了解决在并发环境下cpu缓存失效的情况。 简单来说在一个缓存行中可能存在多个实例的缓存。当其中一个实例的缓存失效需要更新时会让整个缓存行都失效。从而影响到缓存行中的其他对象。 内存对齐后可以理解成同一个缓存行不会存有不同类型的对象即使某个对象的缓存失效也不会影响其他的对象 上面也提到过指针压缩的概念。什么是指针压缩 指针压缩是一种优化技术用于减小程序中指针所占用的内存空间。 在64位系统中一个指针通常需要8个字节。但在许多情况下指针实际指向的地址并不需要使用那么多的位来表示因为程序的内存地址空间可能不会达到8字节指针所能表示的范围。 指针压缩技术利用这一点通过降低指针所占用的位数来节省内存空间。这通常是通过将指针存储为较小的数据类型比如32位系统中的4字节来实现的因为在大多数情况下程序的内存地址空间并不会达到需要用到更多位表示的程度。 指针压缩的一个常见实现方式是使用对象偏移量Object Offset来表示指针。在这种情况下指针不再直接存储对象的内存地址而是存储对象相对于某个基准地址如堆的起始地址的偏移量。通过这种方式可以使用较少的位数来表示指针从而节省内存空间。 例如下图左边的部分没有进行指针压缩右边的部分进行了指针压缩。 没有进行指针压缩时当前对象的内存地址是8并且占用了8个字节。进行了内存压缩后指针中不存放真实的地址而是存放编号偏移量。