5.3.9 本地方法栈

前面提到的所有运行时数据区都是在Java虚拟机规范中明确定义的,除此之外,对于一个运 行中的Java程序而言,它还可能会用到一些跟本地方法相关的数据区。当某个线程调用一个本地 方法时,它就进人了一个全新的并且不再受虚拟机限制的世界。本地方法可以通过本地方法接 口来访问虚拟机的运行时数据区,但不止于此,它还可以做任何它想做的事情。比如,它甚至 可以直接使用本地处理器中的寄存器,或者直接从本地内存的堆中分配任意数量的内存等等。 总之,它和虚拟机拥有同样的权限(或者说能力)。

本地方法本质上是依赖于实现的,虚拟机实现的设计者们可以自由地决定使用怎样的机制 来让Java程序调用本地方法。

任何本地方法接口都会使用某种本地方法找。当线程调用java方法时,虚拟机会创建一个新 的栈帧并压人Java栈。然而当它调用的是本地方法时,虚拟机会保持Java栈不变,不再在线程的 Java栈中压人新的帧,虚拟机只是简单地动态连接并直接调用指定的本地方法。可以把这看做是 虚拟机利用本地方法来动态扩展自己。就如同Java虚拟机的实现在按照其中运行的java程序的吩咐,调用属于虚拟机内部的另一个(动态连接的)方法。


如果某个虚拟机实现的本地方法接口是使用C连接模型的话,那么它的本地方法栈就是C栈。 我们知道,当C程序调用一个C函数时,其栈操作都是确定的。传递给该函数的参数以某个确定 的顺序压入栈,它的返回值也以确定的方式传回调用者。同样,这就是该虚拟机实现中本地方 法栈的行为。

很可能本地方法接口需要回调Java虚拟机中的Java方法(这也是由设计者决定的),在这种 情形下,该线程会保存本地方法栈的状态并进人到另一个java栈。

图5-13描绘了这种情况,就是当一个线程调用一个本地方法时,本地方法又回调虚拟机中的 另一个Java方法。这幅图展示了Java虚拟机内部线程运行的全景图。一个线程可能在整个生命周 期中都执行Java方法,操作它的Java栈;或者它可能毫无障碍地在Java栈和本地方法找之间跳转。

如图5-13所示,该线程首先调用了两个Java方法,而第二个Java方法又调用了一个本地方法, 这样导致虚拟机使用了一个本地方法栈。图中的本地方法栈显示为一个连续的内存空间。假设 这是一个C语言栈,其间有两个C函数,它们都以包围在虚线中的灰色块表示。第一个C函数被 第二个Java方法当做本地方法调用,而这个C函数又调用了第二个C函数。之后第二个C函数又通


过本地方法接口回调了一个Java方法(第三个Java方法),最终这个Java方法又调用了一个java方法(它成为图中的当前方法)。

就像其他运行时内存区一样,本地方法桟占用的内存区也不必是固定大小的,它可以根据 需要动态扩展或者收缩。某些实现也允许用户或者程序员指定该内存区的初始大小以及最大、最小值。

原文地址:https://www.cnblogs.com/mongotea/p/11979481.html