jvm原理(31)栈帧与操作数栈剖析及符号引用与直接引用的转换

Posted 魔鬼_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jvm原理(31)栈帧与操作数栈剖析及符号引用与直接引用的转换相关的知识,希望对你有一定的参考价值。

修改一下上一节的程序:

public class MyTest3 
    public void test() throws FileNotFoundException,IOException,NullPointerException
        try 
            InputStream inputStream = new FileInputStream("test.text");
            ServerSocket serverSocket = new ServerSocket(6666);
            serverSocket.accept();
         catch (FileNotFoundException e) 

         catch (IOException e) 

        catch (Exception ex)

        finally 
            System.out.println("finally");
        

    

我们在test方法上加了throws,throws了三个异常,然后我们在打开jclasslib,会发现多了一个Exceptions的项:
里边的内容就是我们throws的三个异常,这个和异常表是不同的2个概念,异常表会更复杂一点在字节码当中。
0 cp_info #11 java/io/FileNotFoundException
1 cp_info #12 java/io/IOException
2 cp_info #34 java/lang/NullPointerException

slot
在java虚拟机中,每一个线程都对应一个栈帧,所以说这个是线程安全的,对于栈帧来说;对于栈帧我们举例说明:
现在要进行3-2=1这样一个运算,首先会把3和2压入栈,然后遇到操作符减号的时候,需要将3和2弹出栈,然后进行计算3-2=1,得到结果1,然后将结果1压入栈;

途中在栈中的每一个方格就是一个栈帧,一个栈帧就是一个slot,一个栈帧的大小是依据数据类型来定义的,比如int类型的是3为bit,需要一个栈帧,而long类型的是64个bit,需要2个slot,加载long类型的时候需要加载2个slot,slot可以被复用,举例:

public class MyTest4 
     public void test()
         int a = 3;
         if(a<4)
             int b = 4;
             int c = 5;
         
         int d = 7;
         int e = 9;
     

这段代码有5个局部变量,a,b,c,d,e,其中c和b的作用域是在if里边,if执行完毕他们就会被虚拟机垃圾回收器回收,但是他们在局部变量表里边是不会体现出他们各自的生命周期的,当c和b被回收之后,他们占用的slot可能会被d和e复用,slot就好比一个坑,这个坑你蹲完了,我可以接着用这个肯去蹲。也可能不会去复用,不同虚拟机实现是不同的。

符号引用怎么转换为直接引用:
有些符号引用在加载或者第一次使用的时候就会转换为直接引用,这种成为静态的解析;另外一些符号引用则是在每次运行期转换为直接引用,这种转换为动态链接,这体现为java的多态性。

Animal a = new Cat();
a.sleep();
a = new Dog();
a = new Tiger();
a.sleep();

在字节码的角度来看a指向的是Animal 的sleep(),不是Cat,不是Dog,也不是Tiger,挡在运行期间,invokevirtual指令会检查a实际指向的对象,然后将a的sleep的调用转换为实际指向对相关的sleep的调用。这里每次调用都会调用invokevirtual指令,

以上是关于jvm原理(31)栈帧与操作数栈剖析及符号引用与直接引用的转换的主要内容,如果未能解决你的问题,请参考以下文章

JAVA并发编程——源码原理全面剖析与重点梳理

一篇文章帮你搞定JVM中的虚拟机栈

Java 虚拟机原理栈帧 | 局部变量表 | 操作数栈 | 方法出口 | JVM 指令逐条解析

函数栈帧与可变参数列表 p1可变参数列表(完结)( C语言从入门到入土(进阶篇)

JVM总结

JVM-Java栈