LocalVariableTable中的 Slot, 是存在复用现象的,这个我早就知道,但是,不太清楚是如何复用的。

  • Java语言规范与JVM规范都没有对Java语言具体要如何使用JVM的局部变量slot做太多限制,只是规定了参数要从下标为0开始的局部变量区传递而已。作用域不重叠的局部变量之间是否一定要复用局部变量区的slot,这纯粹是实现细节——复用也可以,不复用也完全符合规范。所以这种事情只能针对某个具体实现来讨论。假如题主是用Oracle/Sun JDK或者OpenJDK,那么用JDK自带的javap工具来看看不同样子的源码生成怎样的字节码就可以感受到差别了。
  • 在Oracle/Sun JDK与OpenJDK里的javac实现,分配局部变量slot的方式非常死板,纯粹看几个因素:
  • 声明顺序:先到先得;
  • 作用域:进入作用域时抢最靠前得坑,一离开作用域就放开这个坑,让后面的作用域的变量可以占坑;
  • 类型:long与double占俩相邻slot,其它类型占一个slot。

我用的Java版本是Hotspot ,如下,也是有这样的现象的。

java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)

一个关键点是作用域,什么是java中变量的作用域?它范围是,从定义变量的那一行开始,到对应的代码块结束的那一行。那么什么是代码块呢? 包含它的花括号的整个部分就是 一个代码块。

看一个例子,如下的代码:

    private static void test1() throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
for (int i = 0; i < 3; i++) {
int ia = 1;
long long1 = 2;
int ib = 3;
long long2 = 555;
System.out.println(" over = ");
} ArrayList<Integer> array=new ArrayList<Integer>();
array.add(1);
for (int i=0;i<array.size();i++) {
System.out.println(array.get(i));
Integer ia=array.get(i);
Integer ib=array.get(i);
System.out.println(ia);
}
// int i = ia + ib;
}

javap得到的字节码是:

 LocalVariableTable:
Start Length Slot Name Signature
9 20 1 ia I
13 16 2 long1 J
16 13 4 ib I
21 8 5 long2 J
2 33 0 i I
82 16 2 ia Ljava/lang/Integer;
91 7 3 ib Ljava/lang/Integer;
54 50 1 i I
43 62 0 array Ljava/util/ArrayList;

Slot 值出现了重复的0,1,2... ,可见,Slot就是出现了复用。Slot的占用是按照变量在源码出现的顺序来的。 不过,奇怪的是,从上面的信息看来,Slot并不是按字节码信息LocalVariableTable表的顺序来的,Start,Length,Name,Signature都不是的。 ia占用1个slot,long1是2个(尽管long1的起始的slot还是2,但是我们从ib 的起始slot可以推测),long2 起始的slot是5,那么它占用了几个slot呢?从上面的字节码信息,我们并看不出上面东西呢,我们只能根据经验推测, 经验就是

long与double占俩相邻slot,其它类型占一个slot

如果非要看到long2 占用了几个slot,那么就需要再在其对应的作用域中long2 后面创建另外的变量,那么然后就可以通过它后面的变量的起始slot 推测了。

另外,我测试的时候,发现如果变量定义的位置是作用域最后一行的话,也就是说如果定义了变量,后面没有其他代码了,那么它是不会出现在LocalVariableTable表中的。为什么会这样?我想是因为这个时候它就完全无用了吧。如果要让它出现在LocalVariableTable表中,那么只要在其后面随便写点什么代码就好了!

需要注意的是,如果我们的方法,整个就一个作用域,是不会出现slot复用的,因为无法复用啊,一个方法什么情况会出现多个作用域呢? 其实很简单,一个while循环,或者for,或者if.. else,或者switch等等, 还有就是单单一个 花括号 包围也可以。

参考:

https://www.zhihu.com/question/41694588

LocalVariableTable之 Slot 复用的更多相关文章

  1. jvm slot复用

    如果当前字节码PC计数器的值已经超出了某个变量的作用域,那这个变量对应的Slot就可以交给其他变量使用. 字节码PC计数器就是程序计数器,程序计数器记录当前线程所执行的字节码的偏移地址.如果这个值超出 ...

  2. 局部变量表中Slot复用对垃圾回收的影响详解

    看两段代码 1. package com.jvm; public class Test { public static void main(String[] args) { { byte[] plac ...

  3. vue slot 复用

    话不投机半句多,直接上代码 有3步 第一步:创建渲染slot的组件 重要 第二步:为slot添加父组件数据(props) 重要 第三步:使用 第一步:创建渲染slot的组件 首选创建一个单文件组价,由 ...

  4. JVM 内存区域 (运行时数据区域)

    JVM 内存区域 (运行时数据区域) 链接:https://www.jianshu.com/p/ec479baf4d06 运行时数据区域 Java 虚拟机在执行 Java 程序的过程中会把它所管理的内 ...

  5. 浅谈JVM - 内存结构(二)- 虚拟机栈|凡酷

    2.1 定义 Java Virtual Machine Stacks(Java虚拟机栈) Java 虚拟机栈描述的是 Java 方法执行的内存模型,用于存储栈帧,是线程私有的,生命周期随着线程启动而产 ...

  6. 深入理解JVM—字节码执行引擎

    原文地址:http://yhjhappy234.blog.163.com/blog/static/3163283220122204355694/ 前面我们不止一次的提到,Java是一种跨平台的语言,为 ...

  7. net.ipv4.tcp_tw_recycle

    原创 2016-03-07 CFC4N 运维帮 本文为翻译英文BLOG<Coping with the TCP TIME-WAIT state on busy Linux servers> ...

  8. JVM-5.字节码执行引擎

    一.概述 二.栈帧结构 三.方法调用 四.方法执行       一.概述 虚拟机与物理机 虚拟机是一个相对于物理机的概念,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器.硬件. ...

  9. Java虚拟机运行时栈帧结构--《深入理解Java虚拟机》学习笔记及个人理解(二)

    Java虚拟机运行时栈帧结构(周志明书上P237页) 栈帧是什么? 栈帧是一种数据结构,用于虚拟机进行方法的调用和执行. 栈帧是虚拟机栈的栈元素,也就是入栈和出栈的一个单元. 2018.1.2更新(在 ...

随机推荐

  1. linux下tomcat的启动,停止,重启脚本

    1.tomcat的启动脚本 #vi start_tomcat.sh pid=`ps -ef |grep tomcat |grep -v grep|awk '{print $2}'`       ##定 ...

  2. 关于mysql中存储json数据的读取问题

    在mysql中存储json数据,字段类型用text,java实体中用String接受. 返回前端时(我这里返回前端的是一个map),为了保证读取出的数据排序错乱问题,定义Map时要用LinkedHas ...

  3. poj 1113 凸包

    #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> ...

  4. Python assert(断言)

    Python assert(断言)可以分别后面的判断是否正确,如果错误会报错 示例: a = 1 assert type(a) is int print('No problem') 输出结果: No ...

  5. 18.21 关键字extern

    用#include可以包含其他头文件中变量.函数的声明,为什么还要extern关键字? 1.头文件 其实头文件对计算机而言没什么作用,只是在预编译时在#include的地方展开一下,没别的意义了.将头 ...

  6. 剑指offer 7. 递归和循环 斐波那契数列

    题目描述 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0). n<=39 简简单单 废话不多说,直接上代码: public class Sol ...

  7. VS调试快捷键配置更改

    VS进行调试时,默认情况下需按下Fn+F5等组合按键,手短的用起来很不便利 如何去掉组合键只按下F5? 解决:即按下Fn+Esc,然后就可以直接按下F1-F12使用VS的快捷键,如果想回到组合键也是同 ...

  8. AllocateHWnd SetTimer API

    unit Unit2; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  9. 2、冒泡排序法(C语言)

    一.冒泡算法实现分析 1.假设有5个元素分别为8,6,15,9,3对其进行冒泡排序,我们需要关注的有三点如下: (1)元素个数 n: (2)需要比较的趟数 i: (3)每趟比较的次数 j: 2.它们之 ...

  10. 提取配置文件中无注释的内容方法--findstr

    findstr /v /r # nginx.conf C:\Users\Liang>findstr /?在文件中寻找字符串. FINDSTR [/B] [/E] [/L] [/R] [/S] [ ...