zoukankan      html  css  js  c++  java
  • 局部变量表

    局部变量表示栈帧的重要组成部分之一。

     
    它用于保存函数的参数以及局部变量
     
    局部变量表中的变量只在当前函数调用中有效,当函数调用结束后,随着函数栈帧的销毁,随之销毁。
     
    由于局部变量表在栈帧之中,因此,如果函数的参数和局部变量较多,会使得局部变量表膨胀,从而每一次函数调用就会占用更多的栈空间,最终导致函数的嵌套调用次数减少。
    import com.sun.org.apache.regexp.internal.RE;

    /**
    * Created by wb-xxd249566 on 2017/3/31.
    */
    public class TestStackDeep {
    private static int count=0;

    public static void recursion(long a,long b,long c){
    long e=1,f=2,g=3,h=4,i=5,j=6,k=7,l=8,m=9,n=10;
    count++;
    recursion(a,b,c);
    }

    public static void recursion(){
    count++;
    recursion();
    }
    public static void main(String[] args){
    try {
    // recursion();
    recursion(0l,0l,0l);
    }catch (Throwable e){
    System.out.println("deep of calling = "+count);
    // e.printStackTrace();
    }
    }
    }
    俩次执行的结果:
     
    可以看到,在相同的栈容量下,局部变量少的函数可以支持更深的函数调用。
     
    使用jclasslib工具可以更进一步查看函数的局部变量信息。
     


     可以看到,在Class文件的局部变量表中,显示了每个局部变量的作用域范围、所在槽位的索引(index列)、变量名(name列)和数据类型(J表示long型)。
    栈帧中的局部变量表中的槽位是可以重用的,如果一个局部变量过了其作用域,那么在其作用域之后申明的新的局部变量就很有可能会服用过期局部变量的槽位,从而达到节省资源的目的。
    import com.sun.org.apache.regexp.internal.RE;

    /**
    * Created by wb-xxd249566 on 2017/3/31.
    */
    public class IndexReuse {

    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;
    }
    }
    在localvar1()函数中,局部变量a和b都作用到了函数末尾,故b无法复用a的位置。
    在localvar2()函数中,局部变量a在作用域外不再有效,故局部变量b可以复用a的槽位(1个字)
     
     
     
     局部变量表中的变量也是重要的垃圾回收根节点,只要被局部变量表中直接或间接引用的对象都是不会被回收的。
    通过示例展示局部变量对垃圾回收的影响:
    /**
    * Created by wb-xxd249566 on 2017/3/31.
    */
    public class LocalVarTabGc {

    public void localvarGc1(){
    byte[] a = new byte[6*1024*1024];
    System.gc();
    }

    public void localvarGc2(){
    byte[] a = new byte[6*1024*1024];
    a = null;
    System.gc();
    }

    public void localvarGc3(){
    {
    byte[] a = new byte[6*1024*1024];
    }
    System.gc();
    }

    public void localvarGc4(){
    {
    byte[] a = new byte[6*1024*1024];
    }
    int c = 10;
    System.gc();
    }

    public void localvarGc5(){
    localvarGc1();
    System.gc();
    }

    public static void main(String[] args){
    LocalVarTabGc ins = new LocalVarTabGc();
    ins.localvarGc5();
    }
    }
    在上述代码中,每一个localvarGcN()函数都分配了一块6MB的堆空间,并使用局部变量表引用这块空间。
    localvarGc1() 中,在申请空间后,立即进行垃圾回收,由于byte数组被变量a引用,因此无法回收这块空间:

     localvarGc2()中,在申请空间后,将变量a置为null,使byte数组失去强引用,故垃圾回收可以顺利回收byte数组:
    localvarGc3()中,在申请空间后,虽然使局部变量a失效,a已经离开了作用域,但是变量a依然存在于局部变量表中,并且也指向这块byte数组,故依然无法回收:

     localvarGc4()中,在垃圾回收之前,不仅使变量a失效,离开了作用域,更是申明了变量c,使c复用了a的字,由于a此时已被销毁,故可以回收byte数组:
     
    localvarGc5(),第一次GC后byte数组所存在的局部变量表已经被销毁,byte数组失去引用,因此第二GC时被回收:
     
  • 相关阅读:
    【Mybatis-Plus进阶学习(八)】SQL注入器
    【Mybatis-Plus进阶学习(七)】动态表名SQL解析器
    【Mybatis-Plus进阶学习(六)】多租户SQL解析器
    【Mybatis-Plus进阶学习(五)】性能分析插件
    【Mybatis-Plus进阶学习(四)】乐观锁
    【Mybatis-Plus进阶学习(三)】自动填充
    docker相关操作【动态更新ing】
    Git操作汇总【动态更新ing】
    Go 基准测试和性能测试学习使用
    Go语言的omitempty
  • 原文地址:https://www.cnblogs.com/xxdfly/p/6651610.html
Copyright © 2011-2022 走看看