JVM中的Java虚拟机栈及本地方法栈

122 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

JVM中的Java虚拟机栈

一、虚拟机栈的基本内容

1、概述

Java虚拟机栈是线程私有的。每个线程在创建时都会创建一个虚拟机栈,栈内部保存一个个的栈帧。一个栈帧对应一个方法,随着方法的调用和执行完毕,相应的栈帧执行入栈和出栈。

在java程序中,main方法是一个主线程。

2、特点

  • 生命周期和线程保持一致;
  • 主管Java程序的运行,栈是运行时的单位,堆是存储的单位,也就是说:==栈解决程序的运行问题,即程序如何执行,或者说如何处理数据;堆解决的是数据存储的问题,即数据怎么放、放在哪儿==;
  • 栈保存方法的局部变量(8种基本数据类型、对象的引用地址),部分结果,并参与方法的调用和返回。==这里的对象的引用地址指的就是地址,对象是在堆中存放,每个对象均有一个地址,栈中存放的就是这个地址(指针)==;
  • 栈存在溢出(OOM)问题,不存在垃圾回收(GC)问题

二、栈的内部结构和运行原理

1、内部结构

  • 栈中的数据是以栈帧的格式存在,栈帧是一个内存块,维系着方法执行过程中的数据信息;
  • 局部变量表
  • 操作数栈(或表达式栈)
  • 动态链接(或指向运行时常量池的方法引用)
  • 方法返回地址

2、运行原理

  • 只有入栈和出栈操作;
  • 在一条活动线程中,一个时间点上只有一个活动的栈帧。也就是说只有当前正在执行的方法的栈帧是有效的——当前栈帧(Current Frame),也就是栈顶栈帧;
  • 执行引擎中的所有字节码指令只对当前栈帧操作有效;
  • 如果当前方法内又调用其他方法,那么就会有一个新的栈帧入栈,成为栈顶栈帧;
  • 不同的线程中,栈帧之间是不可能相互引用的;
  • Java中有两种返回函数的方式,return指令和抛出异常,这两种方式都会使当前栈帧被弹出;

三、局部变量表结构

局部变量表又称为局部变量数组

  • 它定义为一个数组,主要用于存储方法参数和==方法体内==的局部变量(在这里要和类中的成员变量区分开来);
  • 局部变量表中的存储空间以局部变量槽(Slot)来表示,64位长度的类型占用两个,32位的占用一个,并且局部变量表的内存空间(即变量槽的数量)是在编译的时候就已经确定(编译过程是在进入JVM之前进行的);
  • 方法嵌套的调用次数由栈的大小来决定,而栈的大小依赖于局部变量表; 在这里插入图片描述

四、其他

1、数据类型

Java中有两种数据类型:基本数据类型和引用类型。

(1)基本数据类型

  • 8种基本数据类型:byte,short,int,long,char,float,double,boolean;
  • 其代表的值就是其本身,具有固定的长度;

(2)引用数据类型

  • 类、数组、接口;
  • 其代表的并不是对象本身,而是对象的地址,代表某个对象的引用;

2、javap -v 字节码文件名.class

在idea中的local中输入:javap -v 字节码文件名.class 可以对字节码文件进行解析,可以查看栈帧信息、常量池信息等。 ps:在输入命令前要使用cd命令进入到文件目录 在这里插入图片描述 也可以在idea中安装jclasslib Bytecode viewer插件进行可视化。 在这里插入图片描述

本地方法栈

Java和C++之间有一堵由内存动态分配和垃圾回收技术所围成的高墙,墙外面的内向进去,墙里面的人想出来。------《深入理解Java虚拟机》

Native是java访问不到的地方,属于调用底层的C语言。(不是java来实现的方法体) Java在启动一个线程时,会调用start方法,start方法内部有一个start0方法,这个方法就进入本地方法栈,==本地方法栈时用于管理本地方法的调用,而Java虚拟机栈是管理Java方法的调用==。 在本地方法栈(Native Method Stack)中,调用本地方法,通过本地方法接口(JNI)来实现对本地方法库的访问。

在这里插入图片描述 为什么会有这种操作呢?

  • 在Java语言创立之初,C、C++可谓是风靡全球,java语言想要立足,必须要有可调用C、C++程序的接口。随着Java语言的发展,现在不仅调用C/C++程序,也可以调用Python等语言的程序,这就可以融合不同的语言为Java所用!
  • 当Java与底层硬件交互或者与操作系统交互的时候,JVM并不是一个完整的系统,它还要依赖于底层系统的支持,通过本地方法,JVM可以方便的和底层系统如操作系统进行交互。

对于程序员们来说,可能并不常用Native,一般在Java驱动打印机,系统管理生产设备(说白了就是现实生活中的实际设备)的等应用时需要Native。 但是目前针对上述的应用,我们可以使用套接字Socket、http等技术实现通信,所以使用Native更加少了。