首页 > 系统相关 >在Linux下如何使用JNI

在Linux下如何使用JNI

时间:2023-06-28 23:23:20浏览次数:39  
标签:Java public 如何 SayHello 本地 Linux JNI 生成 Hello

本文简要介绍了 JNI 调用规范,及常用函数。我会通过具体示例程序展示了实现一个本地调用的基本步骤。希望对大家有帮助哈。

大家都知道Java是跨平台的,可以说Java的出现带给我们巨大的方便。设想如果我们的应用中需要访问到特定的设备,甚至是仅符合公司内部信息交互规范的设备,或某个特定的操作系统才有的特性,用Java来做显然是十分不方便的,面对这些问题,Sun公司在 JDK1.0 中就定义了 JNI 规范,它规定了 Java 应用程序对本地方法的调用规则。

我将详细说明在 Linux 平台下如何实现本地共享库与 Java 协同工作,老规矩以Hello world为例。

定义一个 Java 类 -- Hello类
 public class Hello 
 { 
	 static 
	 { 
		 try 
		 { 
 // 此处即为本地方法所在链接库名
			 System.loadLibrary("hello"); 
		 } 
		 catch(UnsatisfiedLinkError e) 
		 { 
			 System.err.println( "Cannot load hello library:\n " + 
                                e.toString() ); 
		 } 
	 } 
	 public Hello() 
	 { 
	 } 
 // 声明的本地方法
		 public native void SayHello(String strName); 
 }

这里有两个注意事项:

首先:为要使用的每个本地方法编写本地方法声明,只是必须指定 native 关键字,如下所示:

public native void SayHello(String strName);

其次:必须显式地加载本地代码库。我们需在类的静态块中加载这个库(静态库在类加载时候就会调用)

现在我们来编辑hello.java以生成hello.class文件。

生成本地链接库

要为以上定义的类生成 Java 本地接口头文件,需使用 javah,Java 编译器的 javah 功能将根据 Hello 类生成必要的声明,此命令将生成 Hello.h 文件

生成的 Hello.h 文件 内容如下所示:

 #include  
 /* Header for class Hello */ 
 #ifndef _Included_Hello 
 #define _Included_Hello 
 #ifdef __cplusplus 
 extern "C" { 
 #endif 
 /* 
 * Class:     Hello 
 * Method:    SayHello 
 * Signature: (Ljava/lang/String;)V 
 */ 
 JNIEXPORT void JNICALL Java_Hello_SayHello 
  (JNIEnv *, jobject, jstring); 
 #ifdef __cplusplus 
 } 
 #endif 
 #endif
在与 Hello.h 相同的路径下创建一个 CPP 文件 Hello.cpp

内容如下:

#include "Hello.h"
 #include  
 // 与 Hello.h 中函数声明相同
 JNIEXPORT void JNICALL Java_Hello_SayHello  (JNIEnv * env, jobject arg, jstring instring) 
 { 
   // 从 instring 字符串取得指向字符串 UTF 编码的指针
 const jbyte *str = 
        (const jbyte *)env->GetStringUTFChars( instring, JNI_FALSE ); 
    printf("Hello,%s\n",str); 
	 // 通知虚拟机本地代码不再需要通过 str 访问 Java 字符串。
    env->ReleaseStringUTFChars( instring, (const char *)str ); 
    return; 
 }

这里有三个参数,下面讲一下参数用法:

(1)所有的 JNI 调用都使用了 JNIEnv * 类型的指针,习惯上在 CPP 文件中将这个变量定义为 evn,它是任意一个本地方法的第一个参数。env 指针指向一个函数指针表,在 VC 中可以直接用"->"操作符访问其中的函数。
(2)jobject 指向在此 Java 代码中实例化的 Java 对象 LocalFunction 的一个句柄,相当于 this 指针。
(3)第三个参数就是本地调用中有 Java 程序传进的参数,本例中只有一个 String 型参数。 对于字符串型参数,因为在本地代码中不能直接读取 Java 字符串,而必须将其转换为 C /C++ 字符串或 Unicode。

编译生成共享库。

使用 GCC 时 , 必须通知编译器在何处查找此 Java 本地方法的支持文件,并且显式通知编译器生成位置无关的代码,在我的环境中按如下过程编译:

gcc -I/home/jbuilder/jdk1.3.1/include 
    -I/home/jbuilder/jdk1.3.1/include/linux -fPIC -c Hello.c

生成 Hello.o

gcc -shared -Wl,-soname,libhello.so -o libhello.so Hello.o

生成 libhello.so(这就是linux下动态链接库的文件名格式,就像windows下是.dll文件后缀名类似)

最后通知动态链接程序此共享文件的路径。

export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH
编写一个简单的 Java 程序来测试我们的本地方法

将如下源码存为 A.java:

 import Hello; 
 import java.util.*; 
 public class A 
 { 
	 public static void main(String argv[]) 
	 { 
		 A a = new A(); 
	 } 
	 public A() 
	 { 
		 Hello h = new Hello(); 
		 // 调用本地方法
		 h.SayHello("Hello world"); 			
	 } 
 }

用 javac 编译A.java,生成A.class
向执行普通 Java 程序一样使用 java A,我们会看到在屏幕上出现 Hello  world。
ok,完成!

本文原创地址:https://www.linuxprobe.com/linux-jni.html作者:王毅,审核员:逄增宝

本文原创地址:https://www.linuxprobe.com/linux-jni.html

标签:Java,public,如何,SayHello,本地,Linux,JNI,生成,Hello
From: https://www.cnblogs.com/linuxpro/p/17512824.html

相关文章

  • Linux Mint 21.2 前瞻:触控板手势支持来了
    Linux Mint是一款基于Ubuntu的流行Linux发行版本,其最新版本21.2将于7月发布。据悉,LinuxMint的触摸板手势基于开源软件TouchEgg,该手势功能支持触摸板、触摸屏及平板电脑等终端,用户可以自定义多种手势,在整个Cinnamon桌面环境及各种应用程序中,自由执行不同的操作。......
  • Linux Mint 21.2 前瞻:触控板手势支持来了
    Linux Mint是一款基于Ubuntu的流行Linux发行版本,其最新版本21.2将于7月发布。据悉,LinuxMint的触摸板手势基于开源软件TouchEgg,该手势功能支持触摸板、触摸屏及平板电脑等终端,用户可以自定义多种手势,在整个Cinnamon桌面环境及各种应用程序中,自由执行不同的操作。......
  • Linux Mint 21.2 前瞻:触控板手势支持来了
    Linux Mint是一款基于Ubuntu的流行Linux发行版本,其最新版本21.2将于7月发布。据悉,LinuxMint的触摸板手势基于开源软件TouchEgg,该手势功能支持触摸板、触摸屏及平板电脑等终端,用户可以自定义多种手势,在整个Cinnamon桌面环境及各种应用程序中,自由执行不同的操作。......
  • delphi如何把json传递过来的base64值转成图片
    资料来原:https://blog.csdn.net/red_eye/article/details/129634709   在Delphi中,您可以使用TNetEncoding.Base64.DecodeString方法将JSON传递过来的Base64编码字符串转换为原始二进制数据。然后,您可以将该二进制数据保存为图像文件或将其加载到TImage组件中以显示图像。以......
  • F5Cloud第一期如何在AWS上部署F5 VE​
    F5Cloud第一期如何在AWS上部署F5VEF5VE初始化:配置VLAN,Selfip,LOCALDNS,NTP,创建设备组,创建信任关系peer,组建双机,同步配置......
  • 技术岗/算法岗面试如何准备?5000字长文、6个角度以2023秋招经历分享面试经验
    技术岗/算法岗面试流程是什么样的?技术面都干什么?Coding机试如何准备?技术面考察哪些知识,如何准备?项目八股如何准备?简历要注意什么?怎么做?大家好,我是卷了又没卷、薛定谔的卷的大厂算法工程师「陈城南」。本文会从以上6个问题,全方位、全过程的对技术岗/算法岗校招进行介绍,......
  • Linux 中的 dpkg 命令及示例
    Linux因其稳定性、安全性和灵活性而成为世界上使用最广泛的操作系统之一。Linux操作系统的关键组件之一是包管理系统。正在使用不同的包管理系统,但最流行的系统之一是dpkg系统。在本文中,我们将探讨Linux中的dpkg命令、它的作用以及如何有效地使用它。我还将提供一些示例来......
  • linux D-Bus学习第一天:一次简单的信号通讯
    由于blelinux开发需要,所现在开始学习D-Bus,看到了这篇博客,收获颇丰并对其有了大概的了解博客1:这里现在对之前D-Bus安装时的测试程序进行分析,了解各个函数的含义以及为何使用//服务端代码#include<stdio.h>#include<stdlib.h>#include<string.h>#include<dbus/dbus.h......
  • 如何建立公司网站
    要建立公司网站,可以按照以下步骤进行:第一步、确定网站目标明确的公司网站的目标和用途。确定想要在网站上展示的内容和功能,例如公司介绍、产品或服务信息、联系方式等。第二步、注册域名选择并注册一个与公司名称或品牌相关的域名。确保选择一个简洁、易记的域名,并尽量使用常见......
  • 【Java技术专题】「Guava开发指南」手把手教你如何进行使用Guava工具箱进行开发系统实
    为什么要使用不可变集合不可变集合包括元组和冻结集合,其特点是不能被修改。元组有序、不可变、可包含不同类型元素,不能进行修改、删除操作,可通过索引访问元素。冻结集合是一种无序的集合类型,内部元素不能修改、添加或删除,因此常用于处理集合的不可变。不可变对象有很多优点不可变对......