《JVM第6课》当地方法栈

嚴華  金牌会员 | 2024-10-31 09:26:22 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 915|帖子 915|积分 2745

1 什么是当地方法

起首要知道什么是当地方法,当地方法并不是 JVM 自己的方法,也不是 jre 内里的方法,而是指那些操作体系自己的方法(如C/C++方法),它们在操作体系目录里。可以这么理解,当地方法就是计算机操作体系对外提供的方法,JVM 通过调用这些方法可以实现 Java 程序和计算机的交互。
1.1 当地方法的利益


  • 访问操作体系资源:直接调用操作体系的API,例如文件体系、网络接口、图形用户界面等。
  • 性能优化:对于某些计算密集型任务,利用C或C++等语言实现可以显著提高性能。
  • 利用现有库:利用已经存在的C/C++库,避免重复开发和维护。
  • 硬件访问:直接访问硬件设备,例如摄像头、传感器等。
所以如果我们想优化计算密集型任务的性能,或是调用 Java 中没有实现的计算机功能,我们可以自己实现一个当地方法。
1.2 声明当地方法

在Java中,当地方法通过native关键字声明。例如:
  1. public class MyClass {
  2.     // 声明本地方法
  3.     public native void nativeMethod();
  4.     // 静态块中加载本地库
  5.     static {
  6.         System.loadLibrary("mylib"); // 加载名为mylib的本地库
  7.     }
  8.     public static void main(String[] args) {
  9.         new MyClass().nativeMethod(); // 调用本地方法
  10.     }
  11. }
复制代码
1.3 实现当地方法

当地方法的实现通常利用JNI(Java Native Interface)或JNA(Java Native Access)来完成。以下是利用JNI实现当地方法的步骤:
1. 生成头文件

利用javah工具生成包罗当地方法署名的C头文件。假设上面的Java类保存为MyClass.java,编译后生成MyClass.class,然后运行:
  1. javah -jni MyClass
复制代码
这将生成一个名为MyClass.h的头文件,内容如下:
  1. /* DO NOT EDIT THIS FILE - it is machine generated */
  2. #include <jni.h>
  3. /* Header for class MyClass */
  4. #ifndef _Included_MyClass
  5. #define _Included_MyClass
  6. #ifdef __cplusplus
  7. extern "C" {
  8. #endif
  9. /*
  10. * Class:     MyClass
  11. * Method:    nativeMethod
  12. * Signature: ()V
  13. */
  14. JNIEXPORT void JNICALL Java_MyClass_nativeMethod
  15.   (JNIEnv *, jobject);
  16. #ifdef __cplusplus
  17. }
  18. #endif
  19. #endif
复制代码
2. 编写C语言实现

根据生成的头文件,编写C语言实现。例如:
  1. #include <jni.h>
  2. #include <stdio.h>
  3. #include "MyClass.h"
  4. // 实现本地方法
  5. JNIEXPORT void JNICALL Java_MyClass_nativeMethod(JNIEnv *env, jobject obj) {
  6.     printf("Hello from native method!\n");
  7. }
复制代码
3. 编译C代码

将C代码编译成动态链接库。假设C文件名为mylib.c,编译命令如下:
在Linux上:
  1. gcc -shared -o libmylib.so -I/usr/lib/jvm/java-8-openjdk-amd64/include -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux mylib.c
复制代码
在Windows上:
  1. cl -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" -LD mylib.c -Fe mylib.dll
复制代码
4. 运行Java程序

确保动态链接库在Java程序的库路径中,然后运行Java程序:
  1. java -Djava.library.path=. MyClass
复制代码
1.4 利用JNA

JNA是一种更简单的方式来调用当地库,不需要编写C代码。以下是一个利用JNA的示例:

  • 添加JNA依赖:在项目中添加JNA的依赖。如果你利用Maven,可以在pom.xml中添加:
  1. <dependency>
  2.     <groupId>net.java.dev.jna</groupId>
  3.     <artifactId>jna</artifactId>
  4.     <version>5.8.0</version>
  5. </dependency>
复制代码

  • 界说接口:界说一个接口来映射当地库中的函数。
  1. import com.sun.jna.Library;
  2. import com.sun.jna.Native;
  3. public interface MyLib extends Library {
  4.     MyLib INSTANCE = Native.load("mylib", MyLib.class);
  5.     void nativeMethod();
  6. }
复制代码

  • 调用当地方法
  1. public class MyClass {
  2.     public static void main(String[] args) {
  3.         MyLib.INSTANCE.nativeMethod(); // 调用本地方法
  4.     }
  5. }
复制代码
1.5 总结

当地方法是Java程序中的一种特殊方法,其声明在Java代码中,但实现由非Java语言编写。通过当地方法,Java程序可以访问操作体系资源、优化性能、利用现有库和直接访问硬件设备。常见的实现方式包罗JNI和JNA。
2 当地方法栈

2.1 特点


  • 线程私有:每个线程都有自己的当地方法栈,与Java虚拟机栈一样,当地方法栈也是线程私有的。
  • 存储结构:当地方法栈中的每个栈帧(Frame)对应一次当地方法的调用。栈帧中包罗当地方法的参数、局部变量、操作数栈等信息。
  • 调用机制:当Java代码调用一个当地方法时,JVM会创建一个新的栈帧并将其压入当地方法栈。当地方法实行完毕后,栈帧会被弹出并丢弃。
2.2 当地方法栈与Java虚拟机栈的区别


  • 用途不同:Java虚拟机栈用于支持Java方法的实行,而当地方法栈用于支持当地方法的实行。
  • 实现方式:Java虚拟机栈的实现由JVM规范规定,而当地方法栈的实现通常依赖于详细的JVM实现和操作体系的ABI(Application Binary Interface)。
  • 数据类型:Java虚拟机栈重要处理Java类型的值,而当地方法栈可能涉及更广泛的C/C++类型或其他原生类型。
2.3 当地方法栈的工作流程


  • 方法调用:当Java代码中调用一个声明为native的方法时,JVM会查找该方法的当地实现。
  • 栈帧创建:JVM为当地方法创建一个新的栈帧,并将其压入当地方法栈。
  • 参数传递:调用当地方法所需的参数会被从Java虚拟机栈复制到当地方法栈的栈帧中。
  • 方法实行:当地方法在当地方法栈中实行,可以访问操作体系资源、硬件设备等。
  • 结果返回:当地方法实行完毕后,结果会被从当地方法栈复制回Java虚拟机栈,然后继承实行Java代码。
  • 栈帧弹出:当地方法栈中的栈帧被弹出并丢弃。
2.4 总结

当地方法栈是JVM中用于支持当地方法调用的重要数据结构。通过当地方法栈,Java程序可以调用用其他语言编写的代码,从而实现更广泛的功能和更高的性能。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

嚴華

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表