从本地方法栈看到jni调用

我们都知道java虚拟机所管理的内存区域包括方法区,堆,虚拟机栈,本地方法栈,程序计数器。
在《深入理解java虚拟机》中,周志明老师对虚拟机栈进行了讲解,但是对本地方法栈却一笔带过。今天我们就来对本地方法栈做下深入......
首先我们先回顾一下虚拟机栈。

1.虚拟机栈

1.1虚拟机栈的特点

虚拟机栈是线程私有的,它的生命周期与线程相同。

1.2虚拟机栈的概念

虚拟机栈是java方法执行的线程内存模型:每个java方法在执行时都会创建一个“栈帧”,栈帧的结构分为“局部变量表,操作数栈,动态链接,方法出口”几个部分。栈帧中的局部变量表存放着一个方法的所有局部变量。
对于java类中的方法来说:方法调用时,创建栈帧,并压入虚拟机栈;方法执行完毕,栈帧出栈并销毁。

1.3关于虚拟机栈的异常

单个线程请求的栈深度大于虚拟机允许的深度,则会抛出StackOverflowError;
当整个虚拟机栈内存耗尽时,无法再申请到内存会抛出OutOfMemoryError;

2.本地方法栈

虚拟机栈服务于java方法,本地方法栈服务于Native方法。

2.1那么何为Native方法?

其实Native方法是一个用native关键字修饰的方法,它实质上就是一个java调用其它语言的接口(像调用C,C++等)。
看到这里想到了什么?JNI调用的时候就是依托于Native方法。

2.2为什么会有native方法

①尽管java很好用,但是效率上不如c和c++
②java需要和底层操作系统或者和硬件交互

3.用native的方式实现jni

(这并不是我们在Android开发中使用的方式,但是原理上是相同的)

3.1 编写我们的Native方法,创建MyNative.java文件

public class MyNative {
	public static native String myPrint();
	static {
		System.loadLibrary("print");
	}
	public static void main(String[] args){
	new MyNative().myPrint();
	}
	
}

3.2 编译.java文件,生成字节码文件

3.3 获取.h文件

通过javah -jni MyNative就会产生一个MyNative.h文件。

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class MyNative */

#ifndef _Included_MyNative
#define _Included_MyNative
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     MyNative
 * Method:    myPrint
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_MyNative_myPrint
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

3.4编写print.cpp文件

#include 'MyNative.h'
JNIEXPORT jstring JNICALL Java_MyNative_myPrint
  (JNIEnv *env, jclass jobj)
{	return env->NewStringUTF("hellonative");
}

3.5 运行,打印结果。

posted @   我的小鱼干嘞  阅读(949)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程
点击右上角即可分享
微信分享提示