JVM 4-本地方法栈

686 阅读3分钟

本地方法栈

0. 前置知识

0.1 java方法

  • 由java语言编写,编译成字节码,存储在class文件中的

  • java方法是与平台无关的

0.2 本地方法

  • 本地方法是由其它语言编写的,编译成和处理器相关的机器代码

  • 本地方法保存在动态链接库中,即.dll(windows系统)文件中,格式是各个平台专有的

  • 本地方法不是平台无关的

0.3 JNI

native关键字修饰的方法即为JNI(Java Native Interface),类似接口方法。

private native void minimizeImpl(long ptr, boolean minimize);

不同在于 虽然JNI也看不到实现体,但实际上是由jvm在加载时调用底层实现的,JNI的实现体不是由java代码写的,而可能由别的语言(如:C/C++)实现,JNI可以理解为连接java代码和其他语言实现的代码的入口。

JNI的实现体是本地方法

在执行Java字节码时如果遇到有某个方法标明为Native的则从JVM中找到对应的其他语言(如:C/C++)函数,一般本地方法对应的函数会被注册到JVM中。

JNI 类本地方法最著名的应该是 System.currentTimeMillis()JNI使 Java 深度使用操作系统的特性功能,复用非 Java 代码。 但是在项目过程中, 如果大量使用其他语言来实现 JNI , 就会丧失跨平台特性。

1. 基本概念

本地方法栈(Native Method Stack)与虚拟机栈所发挥的作用是非常相似的,它们之间的区别不过是虚拟机栈为虚拟机执行 Java 方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的 Native 方法服务。与虚拟机栈一样,本地方法栈区域也会抛出 StackOverflowError 和 OutOfMemoryError 异常。

执行Native方法时,程序计数器值为空

Sun HotSpot 虚拟机直接就把本地方法栈和虚拟机栈合二为一。

线程开始调用本地方法时,会进入一个不再受 JVM 约束的世界。本地方法可以通过 JNI来访问虚拟机运行时的数据区,甚至可以调用寄存器,具有和 JVM 相同的能力和权限。

2. HotSpot中本地方法栈

任何本地方法接口都会使用某种本地方法栈。当线程调用 java 方法时,虚拟机会创建一个新的栈帧并压入 java 栈。然而当它调用的是本地方法时,虚拟机会保持 java 栈不变,不再在线程的 java 栈中压入新的帧,虚拟机只是简单地动态连接并直接调用指定的本地方法。

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

很可能本地方法接口需要回调 java 虚拟机中的 java 方法,在这种情况下,该线程会保存本地方法栈的状态并进入到另一个 java 栈。

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