JVM的栈内存

  每当启动一个新线程时,Java虚拟机都会为它分配一个Java栈。Java栈以帧为单位保存线程的运行状态。虚拟机只会直接对Java栈执行两种操做:以帧为单位的压栈和出栈。多线程

  某个线程正在执行的方法被称为该线程的当前方法,当前方法使用的栈帧称为当前帧,当前方法所属的类称为当前类,当前类的常量池称为当前常量池。在线程执行一个方法时,它会跟踪当前类和当前常量池。此外,当虚拟机遇到栈内操做指令时,它对当前帧内数据执行操做。spa

  每当线程调用一个Java方法时,虚拟机都会在该线程的Java栈中压入一个新帧。而这个新帧天然就成为了当前帧。在执行这个方法时,它使用这个帧来存储参数、局部变量、中间运算结果等数据。线程

  Java方法能够以两种方式完成。一种经过return返回的,称为正常返回;一种是经过抛出异常而异常终止的。无论以哪一种方式返回,虚拟机都会将当前帧弹出Java栈而后释放掉,这样上一个方法的帧就成为当前帧了。code

  Java帧上的全部数据都是此线程私有的。任何线程都不能访问另外一个线程的栈数据,所以咱们不须要考虑多线程状况下栈数据的访问同步问题。当一个线程调用一个方法时,方法的的局部变量保存在调用线程Java栈的帧中。只有一个线程能老是访问那些局部变量,即调用方法的线程。对象

JVM栈之局部变量表:包含参数和局部变量

局部变量表存放了基本数据类型、对象引用和returnAddress类型(指向一条字节码指令的地址)。其中64位长度的long和double类型的数据会占用2个局部变量空间(slot)(下图1到3的缘由),其他数据类型只占用1个。局部变量表所需的内存空间在编译期间完成分配。每一个方法都对应一个栈帧。blog

public class StackDemo {
    
    //静态方法
    public static int runStatic(int i, long l, float f, Object o, byte b) {
        return 0;
    }

    //实例方法
    public int runInstance(char c, short s, boolean b) {
        return 0;
    }

}

其对应的局部变量表以下:内存

上方表格中,静态方法和实例方法对应的局部变量表基本相似。但有如下区别:实例方法的表中,第一个位置存放的是当前对象的引用。get

JVM栈之操做数栈

Java没有寄存器,全部参数传递都是使用操做数栈。同步

public static int add(int a,int b){
        int c=0;
        c=a+b;
        return c;
    }

压栈的步骤以下:虚拟机

  0:   iconst_0 // 0压栈

  1:   istore_2 // 弹出int,存放于局部变量2

  2:   iload_0  // 把局部变量0压栈

  3:   iload_1 // 局部变量1压栈

  4:   iadd      //弹出2个变量,求和,结果压栈

  5:   istore_2 //弹出结果,放于局部变量2

  6:   iload_2  //局部变量2压栈

  7:   ireturn   //返回

若是计算100+98的值,那么操做数栈的变化以下图所示:

35721707-fff7-4516-86a7-dda30320dc06

 

JVM栈之栈上分配(动态链链接)

小对象(通常几十个bytes),在没有逃逸的状况下,能够直接分配在栈上

直接分配在栈上,能够自动回收,减轻GC压力

大对象或者逃逸对象没法栈上分配

相关文章
相关标签/搜索