java局部变量表是栈帧重要组中部分之一。他主要保存函数的参数以及局部的变量信息。局部变量表中的变量作用域是当前调用的函数。函数调用结束后,随着函数栈帧的销毁。局部变量表也会随之销毁,释放空间。

由于局部变量表存在栈帧中。所以,如果函数参数和局部变量比较多,会使的局部变量表膨胀,每一次调用会占用更多的栈空间。最终结局就是栈空间内存一定的情况下调用的次数减少。

1.1.1. 局部变量表变量影响

下面的代码演示在栈空间内存一定的情况下,参数以及局部变量的大小对函数调用次数的影响。第一个函数recursion()不包含任何的参数和局部变量,第二个函数recursion()包含3个参数和4个局部变量,因此我们也可以算出局部变量表中包含了13个变量信息。第一个局部变量表拥有更深的调用层次。代码如下:

private static int count=0;

public static void recursion(int a,int b,int c){

long l1=12;

short sl=1;

byte b1=1;

String s="1";

System.out.println("count="+count);

count++;

recursion(1,2,3);

}

public static void recursion(){

System.out.println("count="+count);

count++;

recursion();

}

使用jvm参数-Xss128K执行上面第一个无参的recursion()函数,输出结果如下:

count=4495

Exception in thread "main" java.lang.StackOverflowError

at sun.nio.cs.UTF_8.updatePositions(UTF_8.java:77)

使用jvm参数-Xss128K执行上面第二个个有参的recursion()函数,输出结果如下:

count=3865

Exception in thread "main" java.lang.StackOverflowError

at sun.nio.cs.UTF_8.updatePositions(UTF_8.java:77)

at sun.nio.cs.UTF_8$Encoder.encodeArrayLoop(UTF_8.java:564)

at sun.nio.cs.UTF_8$Encoder.encodeLoop(UTF_8.java:619)

可以得出结论:

在同等的栈容量下,局部变量少的函数可以支持更深的函数调用。调用次数也就越多。

如何证明结论是正确的呢?在这里我们借助jclasslib工具来查看局部变量表的局部变量信息。

下图显示了无参的recursion()函数最大的局部变量表大小为0个字。有参的recursion()函数最大的局部变量表大小为8个字。在这里说明一下:

int、short、byte、对象引用等占用一个字。long和double在局部变量中需要占用2个字。

(字 一个字在32位计算机中为4个字节的长度)

我们来算一下recursion(1,2,3);方法局部变量表的大小。

三个参数为int

所以 是3

long l1=12; 2

short sl=1; 1

byte b1=1; 1

String s="1"; 1

所以说 一共是8个字。

需要强调的一点是这里说的局部变量表指的是java栈空间的一部分,不要跟下面说的classs字节码中的局部变量表混淆。

下面展示class字节码中的局部变量表的内容:

从图中看以看出来一些信息:

在Class文件的局部变量表定义中,显示了每一个局部变量的作用范围、所在槽位的索引信息(index列信息),

变量的名称(name列)和数据类型信息(descriptor列)

数据类型信息映射:

I---int类型

D--double类型

B-byte类型

Ljava/lange/Integer --Integer类型

Ljava/lange/String--String类型

S--short类型

栈帧中的局部变量的槽位是可以重复使用的。如果一个声明的变量过了其作用域,那么其作用域之后申请的变量有可能复用过期的局部变量的槽位,从而能够达到节省资源目的。

1.1.2. 局部变量表槽位的复用

下面得代码显示了局部变量表槽位的复用。localVar1()函数中,局部变量a和b得范围都是到了函数的末尾所以b是没有办法复用a的卡槽所在的位置。localVar2()函数中,局部变量a在}之后不在有效了,所以b是可以复用a的卡槽的位置都是int类型所以是1个字。程序如下所示:

public void localVar1(){

int a=0;

System.out.println(a);

int b=0;

}

public void localVar2(){

{

int a=0;

System.out.println(a);

}

int b=0;

}

使用jclasslib工具来查看局部变量表的局部变量localVar1()信息如下图:

该函数最大的局部变量大小3个字,卡槽0位为thsi引用(实例方法的第一个局部变量都是this),第一个卡槽位变量为a,第二个卡槽位变量为b,每个变量是1个字所以一共是三个字。

使用jclasslib工具来查看局部变量表的局部变量localVar2()信息如下图:

该函数最大的局部变量大小2个字,卡槽0位为thsi引用(实例方法的第一个局部变量都是this),第一个卡槽位变量为a,第二个卡槽位变量为b,每个变量是1个字

但是b变量复用了a卡槽位所以一共是2个字。

局部变量表也是作为垃圾回收gc的重要参考点,只要被局部变量表中直接或者间接引用的对象都不会被回收。所以必须要理解局部变量表才能理解gc回收机制。

下面的主要讲解说明局部变量对垃圾回收的影响。

1.1.3. 局部变量对垃圾回收的影响

程序代码如下所示:

jvm参数-XX:+PrintGC参数 垃圾回收前后堆得大小

JvmTestLocalVarGc t=new JvmTestLocalVarGc();

t.localvarGc1();

结果输出:[Full GC 3875K->3546K(15872K), 0.0050719 secs]

在申请空间后,立即调用GC垃圾回收,很明显,由于byte被b强引用所以无法回收这块空间。

JvmTestLocalVarGc t=new JvmTestLocalVarGc();

t.localvarGc2();

结果输出:[Full GC 3875K->474K(15872K), 0.0036066 secs]

在垃圾回收前,现将b设置为null,使byte数组拾取引用,所以GC后byte数组被直接垃圾回收了。

JvmTestLocalVarGc t=new JvmTestLocalVarGc();

t.localvarGc3();

结果输出:[Full GC 3875K->3546K(15872K), 0.0069622 secs]

在进行垃圾回收前,先使局部变量b实现,虽然b离开了作用域,但是变量b亦然存放在局部变量表中。并且指向byte数组,故byte数组亦然没有被回收。

JvmTestLocalVarGc t=new JvmTestLocalVarGc();

t.localvarGc4();

结果输出:[Full GC 3875K->474K(15872K), 0.0037666 secs]

在垃圾回收前,不仅是b失效了,c复用了变量b的字,由于b被销毁,所以byte数组被销毁了。

JvmTestLocalVarGc t=new JvmTestLocalVarGc();

t.localvarGc5();

结果输出:[Full GC 3875K->3546K(15872K), 0.0054367 secs]

[Full GC 3546K->474K(15936K), 0.0036164 secs]

对于localvarGc5()调用localvarGc1()方法,很明显localvarGc1()中没有回收byte数组,但在其返回后他的栈帧被销毁了,自然栈帧中所有的局部变量也没销毁了,容器没了,值当然也不存在了嘛。

所以byte数组失去饮用。在localvarGc5()中被回收了。

java虚拟机 函数表_java虚拟机 jvm 局部变量表实战相关推荐

  1. java虚拟机 函数表_java虚拟机的基本结构如图

    1 java虚拟机的基本结构如图: 1)类加载子系统负责从文件系统或者网络中加载Class信息,加载的类信息存放于一块称为方法区的内存空间.除了类的信息外,方法区中可能还会存放运行时常量池信息,包括字 ...

  2. 如何实现java虚拟机的优化_Java虚拟机JVM优化实战的过程全记录

    前言 Java虚拟机是运行所有Java程序的抽象计算机,是Java语言的运行环境,它是Java 最具吸引力的特性之一.Java虚拟机是通过在实际的计算机上仿真模拟各种计算机功能模拟来实现的,通过Jav ...

  3. java虚拟机内存告警_Java虚拟机总结

    JVM体系四大块: 类的加载 JVM内存结构 GC算法 垃圾回收 GC分析 性能调优 执行引擎 JVM架构图 jvm.arch 一.类的加载机制 类的加载 类的加载,将class文件读入方法区,然后在 ...

  4. java 虚拟机的原理_java虚拟机的原理

    所谓虚拟机,就是一台虚拟的机器.它是一款软件,用来执行一系列虚拟计算机指令,大体上虚拟机可以分为系统虚拟机和程序虚拟机,Visual Box .Vmare就属于系统虚拟机.他们完全是对物理计算机的仿真 ...

  5. JAVA虚拟机 安全区域_Java虚拟机的内存区域

    2020年12月10日 阅读 186 关注 Java虚拟机的内存区域 最近在看<深入理解Java虚拟机>,故此写下自己的学习笔记. JVM 运行时数据区域 Java 虚拟机在执行 Java ...

  6. java虚拟机工作原理图_Java虚拟机工作原理

    首先我想从宏观上介绍一下Java虚拟机的工作原理.从最初的我们编写的Java源文件(.java文件)是如何一步步执行的,如下图所示,首先Java源文件经过前端编译器(javac或ECJ)将.java文 ...

  7. java痴和堆_JAVA虚拟机理解 - 爱笑的痴迷者的个人空间 - OSCHINA - 中文开源技术交流社区...

    JVM定义: JVM(Java Virtual Machine),是一种运行Java程序的软件实现,是虚拟的机器.Java程序与平台无关,它直接在虚拟机中运行. JVM运行过程: JVM将内存分划如下 ...

  8. java虚拟机的内存_Java虚拟机的内存结构

    我们都知道虚拟机的内存划分了多个区域,并不是一张大饼.那么为什么要划分为多块区域呢,直接搞一块区域,所有用到内存的地方都往这块区域里扔不就行了,岂不痛快.是的,如果不进行区域划分,扔的时候确实痛快,可 ...

  9. java虚拟机栈帧_Java虚拟机,运行时栈帧结构

    业余生活要有意义,不要越轨.--华盛顿 引导语 "虚拟机"是一个相对于"物理机"的概念,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器. ...

最新文章

  1. 架构周报:微信后台系统的演进之路
  2. tnsnames.ora无法保存的问题
  3. 7.3.3 多路复用IO(IO multiplexing)
  4. IntelliJ IDEA内存优化最佳实践(转)
  5. js求渐升数的第100位
  6. linux 查看用户上次修改密码的日期
  7. FTP 协议和 HTTP 协议的比较
  8. 完美数:数学宝库中的一颗璀璨明珠
  9. Servlet JSP : web.xml 配置学习
  10. (4)散列函数设计:除留余数法
  11. 又一个停止申请后才知道的功能?QQ至尊保服务“下线” 已试运营三年
  12. 流程控制示例:---3个实例示例:
  13. 数据挖掘概念与技术第三版第一章答案
  14. 基于Python+Django的电影推荐系统毕业设计源码
  15. 学习电商项目的经验总结(三)
  16. if while的用法
  17. 计算机开机太慢,为什么电脑开机很慢
  18. springboot酒店客房管理系统设计
  19. windows 磁盘被写保护怎么办
  20. 软件项目管理复习(一-七章)

热门文章

  1. 【codevs1063NOIP04PJ】合并果子,贪心の钻石
  2. Intel 64/x86_64/IA-32/x86处理器 - 通用指令(2) - 二进制算术指令/十进制算术指令
  3. Eigen官网教程(7)geometry几何模块的实践
  4. Linux| |对于UDP的学习
  5. php新闻列表排序,javascript 新闻列表排序简单封装
  6. ps html css 工具,认识Photoshop(PS)CSS切图必用工具
  7. 物联网卡会锁卡吗_物联网卡在建筑行业中的应用你知道吗?
  8. php处理html数据类型,PHP html_entity_decode() 函数 | 菜鸟教程
  9. wrodpress登录mysql_登陆wordpress后台MySQL错误
  10. 8 reasons why SPIR-V makes a big difference