本博文中所讨论的JVM只是自己看书和教程的个人理解,不太严谨,严谨需要另找详细的资料,对细节把控很到位。
本博文环境:
System OS: Windows10 1909
JDK-Version: 1.8.0_202
JVM: Java HotSpot™ 64-Bit Server VM (build 25.202-b08, mixed mode)
IDE: IDEA2021.3
一、前言
针对于内容JVM运行时数据区概述和总结对JVM中运行时数据区进行了一个整体的介绍,本博文是对运行时数据区中的本地方法栈进行剖析和详解。
我们先来看看整体的图示:
二、本地方法栈
看看官方的解释:
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5.6
要说清楚什么是本地方法栈,就必须要明白什么是本地方法,简单的来说,一个Native Method就是一个Java调用非Java代码的接口。一个Native Method
是这样一个Java方法:该方法的实现由非Java语言实现,比如C。这个特征非Java所有,很多其他的编程语言都有这一机制,比如C++中,你可以用extern "C"
告知C++编译器去调用一个C函数。
A native method is a Java method whose implementation is provided by no-java code.
在定义一个native method时,并不提供实现体(有些像定义一个Java interface),因为其实现体是有非Java语言在外面实现的。
本地接口的作用就是融合不同的编程语言为Java所用,他的初衷是融合C/C++程序。
1.1Native Method?
Java使用起来非常方便,然而有些层次的任务用Java实现起来不容易,或者我们对程序的执行效率在意时,问题就来了。
有时候,Java应用需要与Java外面的环境交互,这是本地方法存在的主要原因。想象一下,如果Java需要与一些底层系统,如操作系统或者某些硬件交换信息时,本地方法就是这样一种交流方式:它为我们提供了一个非常简介的接口,而我们无需去了解Java应用之外的繁琐细节。
任何本地方法接口都会使用某种本地方法栈。当线程调用Java方法时,虚拟机会创建一个新的栈帧并压入Java栈。然而当它调用的是本地方法时,虚拟机会保持Java栈不变,不再在线程的Java栈中压入新的帧,虚拟机只是简单地动态连接并直接调用指定的本地方法。
如果某个虚拟机实现的本地方法接口是使用C连接模型的话,那么它的本地方法栈就是C栈。当C程序调用一个C函数时,其栈操作都是确定的。传递给该函数的参数以某个确定的顺序压入栈,它的返回值也以确定的方式传回调用者。同样,这就是虚拟机实现中本地方法栈的行为。
换句话说,其实和我们Java虚拟栈有些类似,只不过栈帧记录的方法不是一个一个的成员方法,而是通过本地方法来实现入栈和出栈操作。
上面这幅图描述了一个线程在调用Java方法的时候,调用了本地方法,本地方法又调回虚拟机栈中另一个Java方法的场景。
一个线程可能在整个生命周期中都执行Java方法,操作它的Java栈;或者它可能毫无障碍地在Java栈和本地方法栈之间跳转。
该线程首先调用了两个Java方法,而第二个Java方法又调用了一个本地方法,这样导致虚拟机使用了一个本地方法栈。假设这是一个C语言栈,其间有两个C函数,第一个C函数被第二个Java方法当做本地方法调用,而这个C函数又调用了第二个C函数。之后第二个C函数又通过本地方法接口回调了一个Java方法(第三个Java方法),最终这个Java方法又调用了一个Java方法(它成为图中的当前方法)。
参考: