最新要闻
- 环球观察:4个多月第一次!Intel Arc Pro专业显卡终于有了新驱动
- 当前最新:小米“退钱”了:27万小米空气净化器初代用户 每人899元
- 全球快报:小金刚手机杀到1999元 卢伟冰喊话友商:欢迎光明磊落竞争
- 全球播报:人体工学椅从没想过:自己真正的对手会是汽车
- 天天微资讯!日本海滩惊现大量乌贼尸体 绵延200米
- 通讯!青石板路图片(青石板规格)
- 微头条丨喊老公过时了!赵丽颖唐嫣孙俪都这样称呼另一半,网友:甜炸了
- GPT-4救了我狗的命
- 【全球快播报】你敢坐吗?滴滴能打到自动驾驶汽车了
- 环球看点!三爱健康集团(01889)发盈喜 预计2022年度股东应占溢利同比增加约223.6%至2922万元
- 环球新消息丨OpenAI创始人:AI可能毁灭人类 必须开发新技术来解决
- 焦点速递!美亚柏科:公司将对各类 AIGC 内容的检测、AI 生成文本的检测技术及产品进行布局
- 绿牌将会取消?网友:走好不送
- 一图看懂Note 12 Turbo:性价比进行到底 16+1TB仅售2599元
- 一加李杰:用户不会被蒙蔽 将旗舰体验普及到底
- 视讯!哈迷必备!Redmi Buds 4哈利波特版图赏
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
今头条!JNI知识点总结
JNI开发中静态和动态注册
JNI(Java Native Interface)是Java平台提供的一种机制,用于在Java程序中调用本地代码(例如C/C++代码)。 JNI中涉及两种类型的方法注册:静态注册和动态注册。
(资料图片)
静态注册是指将本地方法的名称和实现直接映射到Java类的静态方法。这可以通过在C/C++代码中使用特定命名模式(例如Java_com_example_MyClass_myMethod)来实现。然后,可以使用System.loadLibrary()方法在Java代码中加载本地库,并直接调用本地方法。
动态注册是指在Java代码中使用JNI提供的一组API动态地注册本地方法。使用动态注册,可以在运行时加载本地库,并将方法名称和实现与Java类的实例方法绑定。这样,在Java代码中创建类实例时,可以直接调用本地方法。
静态注册通常比动态注册更快,因为它可以避免在Java代码中使用JNI API注册本地方法。但是,它也有一些缺点。例如,由于本地方法的名称必须遵循特定的命名约定,因此它可能不太灵活。此外,如果在运行时加载本地库时发生错误,将无法捕获它。
动态注册通常更灵活,因为它可以在运行时动态加载本地库并动态注册方法。此外,它也可以避免命名约定的限制。但是,它也比静态注册慢,因为它涉及在Java代码中使用JNI API注册本地方法。
假设有以下Java类:
public class MyNativeClass { static { System.loadLibrary("MyNativeLibrary"); } public static native void myStaticMethod(); public native void myInstanceMethod();}
此Java类具有两种本地方法:静态方法myStaticMethod和实例方法myInstanceMethod。这两个方法的实现将在本地库"MyNativeLibrary"中定义。
下面是静态注册和动态注册的具体示例:
静态注册
假设我们使用以下C/C++代码实现本地方法:
JNIEXPORT void JNICALL Java_com_example_MyNativeClass_myStaticMethod(JNIEnv *env, jclass clazz) { // 实现静态方法} JNIEXPORT void JNICALL Java_com_example_MyNativeClass_myInstanceMethod(JNIEnv *env, jobject obj) { // 实现实例方法}
在静态注册中,必须使用特定的命名约定将本地方法名称映射到Java类的静态方法。在本例中,我们使用的是"Java_com_example_MyNativeClass_myStaticMethod"和"Java_com_example_MyNativeClass_myInstanceMethod"。这些方法必须在本地库中实现。
然后,在Java代码中,我们可以直接调用静态方法myStaticMethod(),如下所示:
MyNativeClass.myStaticMethod();
动态注册
在动态注册中,我们必须在Java代码中使用JNI API动态注册本地方法。以下是动态注册的示例代码:
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env; jclass cls; JNINativeMethod methods[] = { {"myInstanceMethod", "()V", (void*) myInstanceMethod} }; if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6) != JNI_OK) { return JNI_ERR; } cls = (*env)->FindClass(env, "com/example/MyNativeClass"); if (cls == NULL) { return JNI_ERR; } if ((*env)->RegisterNatives(env, cls, methods, 1) < 0) { return JNI_ERR; } return JNI_VERSION_1_6;}JNIEXPORT void JNICALL myInstanceMethod(JNIEnv *env, jobject obj) { // 实现实例方法}
首先,我们实现了JNI_OnLoad()方法,在其中使用JNI API动态注册本地方法。在此示例中,我们只注册了一个实例方法myInstanceMethod()。
然后,在Java代码中,我们可以创建MyNativeClass的实例并调用本地方法myInstanceMethod(),如下所示:
MyNativeClass obj = new MyNativeClass();obj.myInstanceMethod();
总体而言,静态注册和动态注册都可以实现在Java代码中调用本地方法。静态注册更简单,但有一些限制。动态注册更灵活,但需要在Java代码中使用JNI API注册本地方法。
jni的动态注册能解决什么问题
动态注册是JNI的一个功能,它允许我们在C/C++代码中动态地将本地方法与Java类绑定在一起。相对于静态注册,动态注册具有以下优势:
灵活性更高:使用动态注册,我们可以在程序运行时动态地添加或删除本地方法,而不需要重新编译整个程序。
可移植性更好:使用静态注册时,我们需要手动编写Java本地接口(JNI)代码,并将其与C/C++代码一起编译成共享库。这会导致库在不同的操作系统和编译器上表现不一致。而使用动态注册,我们只需要将C/C++代码编译成共享库,然后在Java代码中加载该库即可。
减少代码量:使用静态注册时,我们需要为每个本地方法编写一个Java本地接口(JNI)代码。而使用动态注册,我们可以使用同一个JNI接口方法来处理多个本地方法,从而减少代码量。
jni中方法签名有哪些。怎么选用
在JNI中,方法签名是指用来标识一个方法的唯一字符串,它包括了方法的名称、返回类型和参数列表。方法签名的格式为:(参数类型1, 参数类型2, ... )返回类型
,其中参数类型和返回类型都使用Java的类型描述符来表示。
下面是一些常见的Java类型描述符:
- Z:boolean类型
- B:byte类型
- C:char类型
- S:short类型
- I:int类型
- J:long类型
- F:float类型
- D:double类型
- L类名;:引用类型
- [:数组类型
例如,java.lang.String
的类型描述符为Ljava/lang/String;
,int[]
的类型描述符为[I
。
在JNI中,有几种常见的方法签名格式,如下:
(JNIEnv *, jclass)
:静态方法的签名,参数列表中的第一个参数是JNIEnv指针,第二个参数是jclass对象,表示Java类对象。(JNIEnv *, jobject)
:非静态方法的签名,参数列表中的第一个参数是JNIEnv指针,第二个参数是jobject对象,表示Java对象。(JNIEnv *, jobject, ...)返回类型
:非静态方法的签名,参数列表中的第一个参数是JNIEnv指针,第二个参数是jobject对象,表示Java对象,后面跟着一系列方法参数,最后是返回类型。(JNIEnv *, jclass, ...)返回类型
:静态方法的签名,参数列表中的第一个参数是JNIEnv指针,第二个参数是jclass对象,表示Java类对象,后面跟着一系列方法参数,最后是返回类型。
在选择方法签名时,需要注意以下几点:
- 参数类型和返回类型需要使用Java类型描述符来表示,不同类型之间使用逗号隔开。
- 方法名需要与Java中的方法名保持一致,大小写敏感。
- 对于非静态方法,需要在参数列表中添加一个jobject对象,表示Java对象。对于静态方法,需要在参数列表中添加一个jclass对象,表示Java类对象。
- 参数类型和返回类型应该与Java代码中的类型保持一致。
通常情况下,可以通过在Java代码中使用javap命令来获取方法的签名,然后在JNI代码中使用对应的签名来实现方法的调用。
使用javap命令
在Java中,可以使用javap
命令来查看一个类的方法签名。具体步骤如下:
在命令行中打开终端或命令提示符。
切换到包含要查看方法签名的类的目录。
输入以下命令:
javap -s
其中,
是要查看方法签名的类的名称,不包括.class
后缀名。例如,如果要查看
MyClass
类的方法签名,可以输入以下命令:javap -s MyClass
然后会输出
MyClass
类的所有方法及其签名。例如:
public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)Vpublic void hello(); descriptor: ()V
其中,
descriptor
后面的字符串就是方法的签名。
注意,在使用javap
命令时,需要确保编译器已经编译了该类,并且该类的.class
文件已经存在。如果该类还没有被编译,可以先使用javac
命令进行编译。
另外,如果要查看一个类的所有继承方法和接口方法的签名,可以在javap
命令中加上-s
选项。
JNI和java通讯的原理是什么
JNI(Java Native Interface)是Java提供的一种与本地代码交互的机制。它提供了一组标准的接口和规范,使得Java应用程序可以调用本地库中的函数,并且本地库中的函数也可以调用Java应用程序中的函数。JNI的原理可以简单地概括为以下三个步骤:
Java应用程序通过JNI调用本地库中的函数。在调用之前,Java应用程序需要使用
System.loadLibrary()
或System.load()
方法加载本地库。然后,Java应用程序通过JNI提供的接口将参数传递给本地库中的函数,并且将本地库中函数的返回值传递回Java应用程序。本地库中的函数接收到Java应用程序传递的参数后,通过JNI提供的接口将参数转换为本地代码可以处理的格式,并且调用本地代码中的函数进行处理。
本地代码中的函数处理完毕后,将结果返回给本地库中的函数。本地库中的函数将结果转换为Java应用程序可以处理的格式,并且将结果返回给Java应用程序。
总体来说,JNI的原理就是通过提供一组标准的接口和规范,使得Java应用程序可以调用本地库中的函数,并且本地库中的函数也可以调用Java应用程序中的函数,从而实现Java和本地代码之间的交互。
jni中本地引用和全局引用
JNI(Java Native Interface)中有两种引用类型:本地引用(local reference)和全局引用(global reference)。本地引用和全局引用的主要区别在于它们的生命周期和作用域范围。
本地引用是指在本地方法中创建的引用。它们只在本地方法的执行期间有效,并且不能被跨越多个本地方法调用使用。当本地方法返回时,所有本地引用都会自动失效,并且对应的内存资源也会被回收。如果在本地方法中创建的本地引用不及时释放,就会导致内存泄漏。
全局引用是指可以在Java虚拟机的整个生命周期中使用的引用。它们是通过调用JNI提供的函数NewGlobalRef()
来创建的。全局引用可以被多个本地方法使用,并且在整个Java虚拟机生命周期内都有效。当不再需要全局引用时,可以通过调用JNI提供的函数DeleteGlobalRef()
来释放对应的内存资源。
一般来说,当需要在多个本地方法中使用同一个对象时,可以将其转换为全局引用。同时,在创建本地引用时,应该尽可能地减少其数量,以避免内存泄漏的风险。在使用完本地引用后,应该及时将其释放掉,以释放对应的内存资源。
举个实例
假设有一个Java类MyClass
,其中有一个本地方法nativeMethod()
。在该方法中,需要使用一个本地引用来引用一个Java对象。同时,由于该对象需要在多个本地方法中使用,因此需要将其转换为全局引用。
java
public class MyClass { private Object obj; public native void nativeMethod(); public void setObj(Object obj) { this.obj = obj; } public Object getObj() { return obj; }}
在实现nativeMethod()
方法的本地代码中,需要使用一个本地引用来引用MyClass
对象的obj
属性,并且将其转换为全局引用。可以使用以下代码来实现:
c
JNIEXPORT void JNICALL Java_MyClass_nativeMethod(JNIEnv *env, jobject obj) { // 获取MyClass对象的obj属性 jfieldID fid = (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "obj", "Ljava/lang/Object;"); jobject localRef = (*env)->GetObjectField(env, obj, fid); // 将本地引用转换为全局引用 jobject globalRef = (*env)->NewGlobalRef(env, localRef); // 在这里使用全局引用 // 释放全局引用 (*env)->DeleteGlobalRef(env, globalRef);}
在以上代码中,GetObjectClass()
函数用于获取MyClass
对象的类引用,GetFieldID()
函数用于获取obj
属性的ID,GetObjectField()
函数用于获取obj
属性的值,并将其存储在本地引用localRef
中。接下来,可以使用NewGlobalRef()
函数将本地引用转换为全局引用,并在代码中使用它。最后,通过DeleteGlobalRef()
函数释放全局引用的内存资源。
JNI和JNA的区别是什么JNI(Java Native Interface)和JNA(Java Native Access)都是Java程序与本地代码进行交互的技术。
JNI是Java平台提供的一种机制,它可以使Java程序调用C/C++等本地语言编写的代码,并且可以将Java对象传递到本地代码中。JNI需要开发者手动编写一些本地代码,并且需要进行编译和链接。
JNA是一个开源项目,它提供了一种更为简单的方式,使Java程序可以直接访问本地代码。JNA通过Java反射机制实现本地函数的调用,开发者不需要编写任何本地代码,只需要定义本地函数的接口并提供本地库的名称即可。JNA还支持结构体、指针等复杂类型的传递,并且可以自动进行内存管理。
因此,JNI相对而言更加灵活,可以进行更细粒度的控制,但需要更多的开发工作;而JNA则更为简单,开发效率更高,但可能会牺牲一些灵活性和性能。选择何种技术应该根据具体的需求和场景来决定。
举一个JNA实现实例以下是一个使用JNA实现本地函数调用的简单示例:
假设有一个本地库libmymath.so,其中定义了一个函数add,用于计算两个整数的和。
创建Java接口,定义本地函数的接口。
import com.sun.jna.Library;import com.sun.jna.Native;public interface MyMath extends Library { MyMath INSTANCE = (MyMath) Native.load("mymath", MyMath.class); int add(int a, int b);}
加载本地库,获取接口实例。
MyMath myMath = MyMath.INSTANCE;
调用本地函数。
int result = myMath.add(1, 2);
在这个示例中,我们使用JNA加载了本地库mymath,并定义了一个接口MyMath,其中add函数的参数和返回值类型与本地库中的函数保持一致。在Java代码中,我们可以通过MyMath.INSTANCE获取接口实例,并直接调用add函数来进行本地函数调用。
JNA不是Android官方的
JNA不是Android官方实现的技术,它是一个独立的开源项目。在Android开发中,通常使用的是Android NDK(Native Development Kit)提供的JNI技术来实现Java和本地代码的交互。NDK是Android官方提供的工具集,可以帮助开发者将本地代码集成到Android应用中。
虽然JNA在Android开发中并不常用,但是在其他平台(如Windows、Linux等)上,JNA广泛应用于Java和本地代码的交互。JNA提供了一种更为简单和便捷的方式来进行本地函数调用,相对于JNI更加容易上手和使用,因此得到了不少开发者的青睐。
如何快速生成native方法
可以通过Java SE提供的javah
工具快速生成native方法。
javah
命令可以根据Java类的字节码文件,生成对应的C/C++头文件,以便我们在本地代码中实现native方法。具体步骤如下:
- 编写Java类,在其中定义native方法。
public class MyClass { public native void nativeMethod();}
- 在命令行中切换到Java类所在目录下,使用
javac
命令编译Java类。
javac MyClass.java
- 使用
javah
命令生成C/C++头文件。
javah MyClass
执行上述命令后,会在当前目录下生成一个名为MyClass.h
的头文件,其中包含了Java类中定义的native方法的函数原型。
/* DO NOT EDIT THIS FILE - it is machine generated */#include /* Header for class MyClass */#ifndef _Included_MyClass#define _Included_MyClass#ifdef __cplusplusextern "C" {#endif/* * Class: MyClass * Method: nativeMethod * Signature: ()V */JNIEXPORT void JNICALL Java_MyClass_nativeMethod (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif
- 在本地代码中实现native方法。
在生成的头文件中,可以找到对应native方法的函数原型。我们可以根据函数原型在本地代码中实现native方法,并使用System.loadLibrary
加载对应的本地库。
例如,在C/C++代码中实现nativeMethod
函数的示例代码如下:
#include "MyClass.h"JNIEXPORT void JNICALL Java_MyClass_nativeMethod(JNIEnv *env, jobject obj) { // 实现native方法的代码}
通过以上步骤,我们就可以在Java类中使用定义的native方法,并在本地代码中实现native方法。
关键词:
今头条!JNI知识点总结
天天日报丨【Visual Leak Detector】配置项 ReportTo
【Visual Leak Detector】配置项 SelfTest
环球观察:4个多月第一次!Intel Arc Pro专业显卡终于有了新驱动
当前最新:小米“退钱”了:27万小米空气净化器初代用户 每人899元
全球快报:小金刚手机杀到1999元 卢伟冰喊话友商:欢迎光明磊落竞争
全球播报:人体工学椅从没想过:自己真正的对手会是汽车
天天微资讯!日本海滩惊现大量乌贼尸体 绵延200米
通讯!青石板路图片(青石板规格)
微头条丨喊老公过时了!赵丽颖唐嫣孙俪都这样称呼另一半,网友:甜炸了
项目中如何对XSS统一处理
面向对象设计原则
instanceof的使用
GPT-4救了我狗的命
【全球快播报】你敢坐吗?滴滴能打到自动驾驶汽车了
环球看点!三爱健康集团(01889)发盈喜 预计2022年度股东应占溢利同比增加约223.6%至2922万元
世界头条:用gpt4训练一个简易真人代理
全球热头条丨【Visual Leak Detector】配置项 ReportFile
环球通讯!融创百亿美元境外债务重组成功在即 持债金额超30%的债权人小组已签订重组支持协议
环球新消息丨OpenAI创始人:AI可能毁灭人类 必须开发新技术来解决
焦点速递!美亚柏科:公司将对各类 AIGC 内容的检测、AI 生成文本的检测技术及产品进行布局
聚焦:免费Midjourney AI绘画Prompt提示词平台合集
NCNN 模型推理详解及实战
基于中断的字符串动态显示
全球热推荐:[NOI1999] 生日蛋糕
绿牌将会取消?网友:走好不送
一图看懂Note 12 Turbo:性价比进行到底 16+1TB仅售2599元
一加李杰:用户不会被蒙蔽 将旗舰体验普及到底
视讯!哈迷必备!Redmi Buds 4哈利波特版图赏
首发第二代骁龙7+!Redmi Note 12 Turbo图赏
设备树的概念(四):平台设备驱动和设备树
天天最资讯丨Apache iotdb-web-workbench 认证绕过漏洞(CVE-2023-24829)
Halcon学习教程(一) 之提取十字线中心 图像分割
甲流吃退烧药不退烧怎么办_吃了一粒退烧药多久可以喂奶
环球今日报丨卢伟冰:Note系列全球销量破3.2亿 进入全球单品十强
头条:马斯克为何没做出ChatGPT?揭秘OpenAI创始人的权力斗争
日本推出佛祖版ChatGPT:已经为20多万人解决烦恼
观天下!合资车还咋玩!奇瑞艾瑞泽5 GT上市:起售价仅7.99万
每日快报!Redmi Note 12 Turbo搭载超细四窄边直屏:边框窄至1.42mm!
热消息:一篇文章带你了解面积图
京沪杭等地近期明确将有序放开设摊、允许外摆
全球资讯:德创环保:宁波甬德拟以1.61亿元收购飞乐环保100%股权
每日讯息!12306回应免费坐高铁:积分存在有效期
环球即时看!甄子丹主演!《疾速追杀4》豆瓣8.2分:纯粹动作爽片 超越前作
男子求职竟被要求在杭州本地买房 网友:不是招员工是招客户
环球微动态丨试过网易的新AI后 我发现它很笨 但又很聪明
广汽传祺GS4追尾后定损巡航坏了?保险公司不想理赔
记录--vue刷新当前页面
全球关注:借助 mperf 进行矩阵乘法极致优化
MySQL学习笔记-存储引擎
当前看点!低代码起势,开发者可以早日脱离996了?
今日热议:南钢股份:钢材销量同比下降6.28%,2022年年归母净利润同比下滑48.59%,拟10派2.5元
快讯:《生化危机4:重制版》D加密惹争议 又导致性能问题了
全球观热点:女子地铁照被AI一键脱衣传播 网友:无下限的开发
每日焦点!网友准备冲Redmi Note 12 Turbo哈利·波特版:预算3900元
头条:男子乘错出租车 起步1秒被强制收费6元:走了不到10米
【世界新视野】内存掉入无底洞:没有最便宜 只有更便宜
环球观天下!32、K8S-配置管理之Configmap
世界看点:Python中21道个程序小练习
css设置超过固定长度以省略号显示
全球看点:乒乓球技巧训练这就是高手的水准_乒乓球技巧
全球简讯:瑞银:看好亚股增长潜力 偏好亚洲投资级债券
Twitter将上线离谱新规:非会员甚至无法参与投票
热头条丨九识自动驾驶物流车被曝闯红灯 网友:该怎么记分处罚
速读:“网红”威震天在北京环球影城摔了一跤 客服回应:后续演出正常
【环球新要闻】一个时代结束了!Wii U和3DS在线商店已正式关闭
实时:透明外壳设计!Nothing Ear(2)无线耳机上市 999元
热资讯![HTML]表单标签(form表单域、input输入表单、label标签、select下拉表单、textarea文本域)
C#List的3种排序方法
环球观焦点:韩国有意解禁福岛水产品?在野党呼吁韩总统表态
全球新资讯:收评:两市震荡走弱沪指跌0.19% 人工智能概念冲高回落
全球热头条丨想玩必须升级!Steam将于2024年终止对Win7/8/8.1系统支持
中国科学家发现月球水库 估计蓄水量多达2700亿吨
父母做生意给儿子取名为顾客 当事人:家里有个“顾客”能带来更多顾客
世界最高安全标准 我国自研核电华龙一号西部首堆全面建成
【时快讯】249元 TP-LINK推出新款玄鸟AX3000路由器:3000Mbps满血Wi-Fi 6
观热点:Rust 备忘清单_开发速查表分享
即时焦点:郑州大学河南先进技术研究院2023年硕士研究生拟调剂信息公告已公布
天天热点评!国服一步步被掏空 暴雪国际服支持微信支付宝:价格全面上涨
vivo X Fold2将在博鳌亚洲论坛首秀:采用“天圆地方·两仪万象”设计
每日资讯:网信办:全面清理虚假摆拍短视频
环球观热点:如何应对上手英文工具站的 8 大误区
小程序的车载场景应用
【Visual Leak Detector】配置项 ReportEncoding
数据建模
世界要闻:在.NET7使用NPOI读取Excel如此简单
每日简讯:西门子医疗Syngo Carbon助力贵安医院打破数据孤岛,加速智慧医院建设
每日快播:谁是更好的甜点处理器?锐龙5 7600、酷睿i5-13400对比评测:游戏差距大到不敢相信
终于结束了 特斯拉“退一赔三”案二审败诉后申请再审:法院驳回
笔记本电脑排风扇声音大是怎么回事?笔记本电脑排风扇声音大怎么解决?
nova6最严重的缺点是什么?nova6参数详细价格
哈尔滨有几个电脑城?哈尔滨电脑城地址
折旧率是什么意思?折旧率计算公式
全球今头条!Go语言:通过TDD驱动测试开发为同事写的程序优化提速——初次接触并发与channel
【世界时快讯】非看不可的Redis持久化
选择排序
速递!【Visual Leak Detector】配置项 MaxTraceFrames
flash8怎么下载到电脑上?Flash8的序列号是多少?
大连地铁敞门行驶 线路刚开12天:客服称“原因正在调查”
快资讯丨00后女生毕业当猪场保育员:她认为这行业很有潜力