java 虚拟机栈

6 篇文章 0 订阅

  一、 jvm结构

          栈区作为运行时数据区域的一部分,本文进行浅尝辄止的讨论。

二、虚拟机栈

       ◆ 虚拟机栈(stack)是由一个个的栈帧组成,对应着每一的java方法的调用,且线程私有;

        ◆ 栈帧由局部变量表、操作数栈、动态链接、返回方法地址四部分组成;

        ◆ 栈是一个运行时的单位,解决程序如何执行,数据如何处理的,只有进栈出栈操作,不存在内垃圾收问题,而堆(heap)则是处理数据存储问题,解决数据存储在哪里。

三、栈帧解析

         栈帧由局部变量表、操作数栈、动态链接、返回地址四部分组成

1、局部变量表

        定义一个数字数组,主要存储方法参数和定义在方法中的局部变量,这些数据包括基本数据类型和引用数据类型,以及返回参数的类型;局部变量表的最基本单位是槽(solt),32位以内的类型占用1个槽,64位的占用2个槽;当方法位构造方法或者成员方法,会把该对象存放在index为0的slot处,其余的参数表顺序排列。

 2、操作数栈

        先进后出,在方法执行过程中,根据字节码指令,往栈中写入数据或提取数据,即压栈、出栈操作。某些字节码指令将值压入操作数栈,其余的字节码指令将操作数提取出栈,使用它们后再把结果压入栈中。操作数栈主要用于保存计算过程中的中间结果,同时作为计算过程中的临时变量的存储空间;关于操作数栈运算的遵循以下原则:

     ◆ 代码指令的赋值(=)操作,最后计算;

      ◆ 赋值(=)右边的指令,从左至右加载值,依次压入操作数栈;

     ◆ 计算数值根据运算符优先级计算

     ◆ 自增自减操作直接修改的局部变量表的值,不经过操作数栈

     ◆ 最后赋值之前,临时结果也存在操作数栈中

3、动态链接

       每个栈帧内部包含一个指向运行时常量池中该栈帧所属方法的引用。包含这个引用的目的就是为了支持当前地方的代码能够实现动态链接

4、返回地址

       存放调用该方法的程序计数器的值,即调用该方法指令的下一条指令的地址。 如果方法执行出现异常,会从异常表中获取返回地址,不会从栈帧中获取。

5、附加信息

四、代码展示


public class GcApp {

    public static void main(String[] args) {
       GcApp gcApp = new GcApp();
       gcApp.printNum();
    }

    public   void  printNum(){

        int  a= 10;

        int  b =  15;

        int c = b++;

        System.out.println("a+b="+(a+b));

        System.out.println("a*c="+a*c);
    }
}

          通过反汇编查看printNum()的栈帧局部变量表(

javap  -c  GcApp.class

         操作数栈

 0 bipush 10
 2 istore_1
 3 bipush 15
 5 istore_2
 6 iload_2
 7 iinc 2 by 1
10 istore_3
11 getstatic #5 <java/lang/System.out : Ljava/io/PrintStream;>
14 new #6 <java/lang/StringBuilder>
17 dup
18 invokespecial #7 <java/lang/StringBuilder.<init> : ()V>
21 ldc #8 <a+b=>
23 invokevirtual #9 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;>
26 iload_1
27 iload_2
28 iadd
29 invokevirtual #10 <java/lang/StringBuilder.append : (I)Ljava/lang/StringBuilder;>
32 invokevirtual #11 <java/lang/StringBuilder.toString : ()Ljava/lang/String;>
35 invokevirtual #12 <java/io/PrintStream.println : (Ljava/lang/String;)V>
38 getstatic #5 <java/lang/System.out : Ljava/io/PrintStream;>
41 new #6 <java/lang/StringBuilder>
44 dup
45 invokespecial #7 <java/lang/StringBuilder.<init> : ()V>
48 ldc #13 <a*c=>
50 invokevirtual #9 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;>
53 iload_1
54 iload_3
55 imul
56 invokevirtual #10 <java/lang/StringBuilder.append : (I)Ljava/lang/StringBuilder;>
59 invokevirtual #11 <java/lang/StringBuilder.toString : ()Ljava/lang/String;>
62 invokevirtual #12 <java/io/PrintStream.println : (Ljava/lang/String;)V>
65 return

五、HSDIS汇编

       HSDIS(HotSpot disassembler),一个Sun官方推荐的HotSpot虚拟机JIT编译代码的反汇编插件,直接从网上(https://chriswhocodes.com/hsdis/)下载与本机系统对应的动态库,放置到JDK的bin目录下即可。

       也可下载源码自行编译:

git clone https://github.com/liuzhengyang/hsdis
cd hsdis
tar -zxvf binutils-2.26.tar.gz
make BINUTILS=binutils-2.26 ARCH=amd64
cd  buid

        使用HSDISX有以下jvm参数可用:

-Xcomp : 编译模式执行代码,即JVM会在第一次运行时即将所有字节码编译为本地代码
-XX:+UnlockDiagnosticVMOptions : 解锁诊断功能
-XX:+PrintAssembly : 输出反汇编后的汇编指令

        示例:

java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -Xcomp -XX:CompileCommand=compileonly,*GcApp 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值