《JVM第6课》本地方法栈
1 什么是本地方法
首先要知道什么是本地方法,本地方法并不是 JVM 自己的方法,也不是 jre 里面的方法,而是指那些操作系统自己的方法(如C/C++方法),它们在操作系统目录里。可以这么理解,本地方法就是计算机操作系统对外提供的方法,JVM 通过调用这些方法可以实现 Java 程序和计算机的交互。
1.1 本地方法的好处
- 访问操作系统资源:直接调用操作系统的API,例如文件系统、网络接口、图形用户界面等。
- 性能优化:对于某些计算密集型任务,使用C或C++等语言实现可以显著提高性能。
- 使用现有库:利用已经存在的C/C++库,避免重复开发和维护。
- 硬件访问:直接访问硬件设备,例如摄像头、传感器等。
所以如果我们想优化计算密集型任务的性能,或是调用 Java 中没有实现的计算机功能,我们可以自己实现一个本地方法。
1.2 声明本地方法
在Java中,本地方法通过native关键字声明。例如:
public class MyClass {
// 声明本地方法
public native void nativeMethod();
// 静态块中加载本地库
static {
System.loadLibrary("mylib"); // 加载名为mylib的本地库
}
public static void main(String[] args) {
new MyClass().nativeMethod(); // 调用本地方法
}
}
1.3 实现本地方法
本地方法的实现通常使用JNI(Java Native Interface)或JNA(Java Native Access)来完成。以下是使用JNI实现本地方法的步骤:
1. 生成头文件
使用javah工具生成包含本地方法签名的C头文件。假设上面的Java类保存为MyClass.java,编译后生成MyClass.class,然后运行:
javah -jni MyClass
这将生成一个名为MyClass.h的头文件,内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class MyClass */
#ifndef _Included_MyClass
#define _Included_MyClass
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: MyClass
* Method: nativeMethod
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_MyClass_nativeMethod
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
2. 编写C语言实现
根据生成的头文件,编写C语言实现。例如:
#include <jni.h>
#include <stdio.h>
#include "MyClass.h"
// 实现本地方法
JNIEXPORT void JNICALL Java_MyClass_nativeMethod(JNIEnv *env, jobject obj) {
printf("Hello from native method!\n");
}
3. 编译C代码
将C代码编译成动态链接库。假设C文件名为mylib.c,编译命令如下:
在Linux上:
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上:
cl -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" -LD mylib.c -Fe mylib.dll
4. 运行Java程序
确保动态链接库在Java程序的库路径中,然后运行Java程序:
java -Djava.library.path=. MyClass
1.4 使用JNA
JNA是一种更简单的方式来调用本地库,不需要编写C代码。以下是一个使用JNA的示例:
- 添加JNA依赖:在项目中添加JNA的依赖。如果你使用Maven,可以在
pom.xml中添加:
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.8.0</version>
</dependency>
- 定义接口:定义一个接口来映射本地库中的函数。
import com.sun.jna.Library;
import com.sun.jna.Native;
public interface MyLib extends Library {
MyLib INSTANCE = Native.load("mylib", MyLib.class);
void nativeMethod();
}
- 调用本地方法:
public class MyClass {
public static void main(String[] args) {
MyLib.INSTANCE.nativeMethod(); // 调用本地方法
}
}
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程序可以调用用其他语言编写的代码,从而实现更广泛的功能和更高的性能。
《JVM第6课》本地方法栈的更多相关文章
- JVM体系结构之五:本地方法栈
对于一个运行中的Java程序而言,它还可能会用到一些跟本地方法相关的数据区.当某个线程调用一个本地方法时,它就进入了一个全新的并且不再受虚拟机限制的世界.本地方法可以通过本地方法接口来访问虚拟机的运行 ...
- JVM内存结构之本地方法栈
Native Method Stacks(本地方法栈) 本地方法:指不是用Java语言编写的方法,因为Java语言是有一定限制的,有些情况下它是不能直接和操作系统打交道的.这时就需要调用一些用C或C+ ...
- JVM,JMM,虚拟机栈,本地方法栈
JVM 虚拟机栈 本地方法栈:本地方法(使用native关键词修饰的方法,是由JVM底层用C,C++实现的),运行这部份代码使用的栈就是本地方法栈
- JVM本地方法栈及native方法
看到虚拟机栈和本地方法栈的区别的时候有点疑惑,因为本地方法栈为虚拟机的Native方法服务.以下转载一篇关于native方法的介绍: http://blog.csdn.net/wike163/arti ...
- JVM 运行时数据区:程序计数器、Java 虚拟机栈和本地方法栈,方法区、堆以及直接内存
Java 虚拟机可以看作一台抽象的计算机,如同真实的计算机,它也有自己的指令集和运行时内存区域. Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存(运行时内存区域)划分为若干个不同的数 ...
- JVM方法栈的工作过程,方法栈和本地方法栈有什么区别。
JVM的本地方法栈 对于一个运行中的Java程序而言,它还可能会用到一些跟本地方法相关的数据区.当某个线程调用一个本地方法时,它就进入了一个全新的并且不再受虚拟机限制的世界.本地方法可以通过本地方 ...
- jvm:内存结构(堆、方法区、程序计数器、本地方法栈、虚拟机栈)
1.jvm内存结构 静态编译:把java源文件编译成字节码文件class,这个时候class文件以静态方式存在. 类加载器:把java字节码文件加载到内存中 方法区:将字节码放到方法区作为元数据(简单 ...
- jvm入门及理解(三)——运行时数据区(程序计数器+本地方法栈)
一.内存与线程 内存: 内存是非常重要的系统资源,是硬盘和cpu的中间仓库及桥梁,承载着操作系统和应用程序的实时运行.JVM内存布局规定了JAVA在运行过程中内存申请.分配.管理的策略,保证了JVM的 ...
- JVM 专题九:运行时数据区(四)本地方法栈
1. 本地方法栈 2. 什么是本地方法栈? Java虚拟机栈用于管理Java方法的调用,而本地方法栈用于管理本地方法的调用 本地方法栈,也是线程私有的. 允许被实现成固定或者是可动态拓展的内存大小 ...
- JVM运行时数据区--本地方法栈
本地方法栈 1.Java虚拟机栈用于管理Java方法的调用,而本地方法栈用于管理本地方法(一般非Java实现的方法)的调用 2.本地方法栈,也是线程私有的. 3.允许被实现成固定或者是可动态拓展的内存 ...
随机推荐
- 使用智能AI在农业养殖业中风险预警的应用
一.前言 之前写过一篇<物联网浏览器(IoTBrowser)-使用深度学习开发防浸水远程报警>文章,主要介绍了通过摄像头麦克风监测浸水报警器有无异常,当出现异常后进行紧急报警并推送微信通知 ...
- RabbitMq 初学五大模式 通俗易懂 超详细 【包含案例】
RabbitMQ五种工作模式 HelloWorld 简单模式 WorkQueues 工作队列模式 Publish/Subscribe 发布/订阅模式 Routing 路由模式 Topic 通配符模式 ...
- Linux内核如何访问另外一个模块的函数和变量 原创
一.问题整理 内核中两个模块,一个A,一个B,A模块中有操作函数,B模块要调用A模块的函数. 二.分析 这是一个驱动工程师经常遇到的一个问题,该问题其实是模块符号导出问题,实现该功能比较简单,借助EX ...
- 解决gedit报错无法打开的问题
彻底解决关于gedit的Unable to init server: 无法连接: 拒绝连接_BD_Marathon的博客-CSDN博客_unable to init server: 无法连接: 拒绝连 ...
- R 语言使用
安装 brew install r --formulae 使用 CLI /opt/homebrew/bin/r # 进入 R 交互式编程界面 GUI GUI 有官方的 R Studio,不过界面我不是 ...
- .NET 摄像头采集
本文主要介绍摄像头(相机)如何采集数据,用于类似摄像头本地显示软件,以及流媒体数据传输场景如传屏.视讯会议等. 摄像头采集有多种方案,如AForge.NET.WPFMediaKit.OpenCvSha ...
- 图解Zabbix设置邮件报警
Zabbix设置邮件告警 前提条件: Zabbix Server 和 Zabbix Agent都已安装完毕,并已启动 1.添加主机 2.配置邮件告警,这里以VSFTP服务为例 yum in ...
- 微信小程序之无需服务端支持实现内容安全检查
微信小程序之无需服务端支持实现内容安全检查 微信小程序审核未通过,原因如下: 为避免您的小程序被滥用,请你完善内容审核机制,如调用小程序内容安全API,或使用其他技术.人工审核手段,过滤色情.违法等有 ...
- 《花100块做个摸鱼小网站! 》第五篇—通过xxl-job定时获取热搜数据
️基础链接导航️ 服务器 → ️ 阿里云活动地址 看样例 → 摸鱼小网站地址 学代码 → 源码库地址 一.前言 我们已经成功实现了一个完整的热搜组件,从后端到前端,构建了这个小网站的核心功能.接下来, ...
- R-Adapter:零样本模型微调新突破,提升鲁棒性与泛化能力 | ECCV 2024
大规模图像-文本预训练模型实现了零样本分类,并在不同数据分布下提供了一致的准确性.然而,这些模型在下游任务中通常需要微调优化,这会降低对于超出分布范围的数据的泛化能力,并需要大量的计算资源.论文提出新 ...