zoukankan      html  css  js  c++  java
  • JVM 线程中方法执行过程

     本章节内容参考:《深入理解Java虚拟机》

    运行时数据区:

     本次只介绍用于程序运行的线程私有的内存模型。   

                    虚拟机栈(FILO):java方法执行的内存模型。

                        栈帧(线程执行的一个方法的内存模型,每调用一个方法,压入一个栈帧)

                                  局部变量表:编译器可知的8种基本类型、reference类型、returnAddress类型

                                  操作数栈:一个用于计算的临时数据存储区(明显,此栈是为了存放要操作的数据用的)

                                  动态链接:支持java多态

                                  返回地址:方法结束的地方。return/Exception        

                    本地方法栈:Native方法执行的内存模型。

                    程序计数器:这个计数器记录的是正在执行的虚拟机字节码指令的地址(如果线程正在执行的是一个java方法)。 字节码解释器工作时,就是通过改变这个计数器的值来选取需要执行的字节码                                         指令(分支,循环,跳转、异常处理、线程恢复)

    线程中,方法A调用方法B。

    线程的执行的过程:

        1、线程开始,分配虚拟机栈大小(JVM参数 -Xss:大小,1.5+默认1M),

             2、执行方法A时,创建一个栈帧A压入虚拟机栈顶,根据程序计数器中的记录的下一个要执行的字节码指令的地址,找到并执行指令(将要操作的数据压入操作数栈栈顶,将操作结果放入局部变量表中,详细过程参照下面“合代码演示”部分)。

            3、中间调用方法B,则创建栈帧B,接着执行方法B的指令,直到方法B结束(遇到方法返回的字节码指令或异常),B栈帧出栈,如果有返回数据,将返回数据压入栈帧A的操作数栈顶,方法A接着执行。 

      4、方法A执行结束,弹出栈帧A,虚拟机栈中再无栈帧,此线程结束。 

    为更形象的理解,结合代码演示(操作数栈和局部变量表):

    源码:

    25.      public void add() {

    26.           int a = 3;

    27.           int b = 4;

    28.           int c = a + b;

    29.     }

    javap结果:

    public void add();

        descriptor: ()V

        flags: ACC_PUBLIC

        Code:

      //操作数栈最大深度2,局部变量4, 方法入参1(this + 真正的入参, 如果是方法名add(int a, int b),args_size = 1(this) + 2(a和b) = 3)

           stack=2,   locals=4, args_size=1

             0: iconst_3     // 将int类型常量3压入操作数栈顶

             1: istore_1     // 将操作数栈顶的数据弹出,存入局部变量表索引1

             2: iconst_4     // 将int类型常量4压入操作数栈栈顶

             3: istore_2     // 将操作数栈顶的数据弹出,存入局部变量表索引2

             4: iload_1      // 将局部变量表索引为1的数据加入到操作数栈顶

             5: iload_2      // 将局部变量表索引为2的数据加入到操作数栈顶

             6: iadd          // 将栈中2个数相加,将结果入栈顶 

             7: istore_3     // 将栈顶结果弹出,存入局部变量表索引3

             8: return

          LineNumberTable:

            line 26: 0 //java文件代码第26行对应开始指令0

            line 27: 2 //java文件代码第26行对应开始指令2

            line 28: 4 //java文件代码第26行对应开始指令4

            line 29: 8 //java文件代码第26行对开始应指令8

          LocalVariableTable:  // 局部变量表,4个局部变量,this、a、b、c

            Start  Length  Slot  Name   Signature

                0       9     0  this   LCongoPengYuyan;         

                2       7     1     a   I

                4       5     2     b   I

                8       1     3     c   I

    一些思考:

      我们都知道,操作数栈存放的数据是(int、long、float、double、reference、returnType)这些类型,

      reference指像的对象是在堆里面,堆是共享的,既然是所有线程共享的,为啥在多线程中,数据会不一致呢,线程A将对象O的某个属性改了,而线程B拿到O的属性的值还是未改变的?java还推出了统一的JMM模型。

           其实,CPU执行的时候,是要将内存中的数据,加载到CPU缓存(寄存器等),多线程的时候,数据首先在寄存器中修改,改完后重新刷入内存中。解决多线程数据可见性的问题,java提供了Volatile关键字,

      它的实现原理,对象操作后面加入Lock汇编指令。A线程在修改操作后,强制刷入主存,然后通知执行B线程的CPU,你CPU缓存中的值是失效,不能用了,要用请从主存中重新获取。

     

  • 相关阅读:
    Fortify Audit Workbench Cookie Security: Cookie not Sent Over SSL
    Fortify Audit Workbench 笔记 Access Control: Database
    MATLAB中的polyfit函数的使用方法
    编写python代码时出现SyntaxError: invalid character in identifier的解决方法
    Windows10安装MinGW-W64出现Cannot download repository.txt的一种解决方法
    使用IDM下载B站视频出现声音跟视频分离的一种解决方法
    简洁桌面(使用Windows自带的桌面整理功能)
    MATLAB标记图像中特殊的点
    解决python使用pip安装下载库出现错误:ERROR:Cannot unpack file xxxx情况
    解决python使用pip下载安装库速度慢问题
  • 原文地址:https://www.cnblogs.com/sleepingDogs/p/11032471.html
Copyright © 2011-2022 走看看