程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

Java本地方法调用

发布于2021-06-12 15:02     阅读(570)     评论(0)     点赞(15)     收藏(2)


JNI介绍

JNI是Java Native Interface的缩写,中文为JAVA本地调用。从Java 1.1 开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。

使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的,比如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少保证本地代码能工作在任何Java 虚拟机实现下。

JNI的使用场景

  1. Java应用需要与本地其它非Java应用交互
  2. 遇到性能瓶颈,通常本地代码执行效率要优于Java代码
  3. JDK提供的功能不足以帮我们实现需要的功能

JNI的问题

  1. 因为JNI有一个Native这个特点,一点有项目用了JNI,也就说明这个项目基本不能跨平台了。
  2. JNI调用是相当慢的,在实际使用的之前一定要先想明白是否有这个必要。
  3. 因为C++和C这样的语言非常灵活,一不小心就容易出错,比如代码就没有写析构字符串释放内存,就存在内存泄漏的问题,对于java developer来说因为有了GC 垃圾回收机制,所以大多数人没有写析构函数这样的概念。所以JNI也会增加程序中的风险,增大程序的不稳定性

JNI实战

主要分为以下几个步骤

  • 编写带有native声明的方法的java类
  • 使用javac命令编译所编写的java类
  • 使用javah -jni 类的全限定名 生成扩展名为h的头文件
  • 使用C/C++实现本地方法
  • 将C/C++编译的文件生成动态连接库

1.编写java程序

1.这里以HelloWorld为例,java代码如下:

class HelloJni {
public native void sayHello(String name);
static {
System.loadLibrary("hello");
}
public static void main(String[] args) {
new HelloJni().sayHello("java");
}
}

声明native方法:如果你想将一个方法做为一个本地方法的话,那么你就必须声明改方法为 native的,并且不能实现。

Load动态库:System.loadLibrary(“hello”);加载动态库(我们可以这样理解:我们的方法 displayHelloWorld()没有实现,但是我们在下面就直接使用了,所以必须在使用之前对它进行初始化)这里一般是以static块进行加载的。同时需要注意的是System.loadLibrary();的参数“hello”是动态库的名字。

2.然后进行编译

打开控制台,进入java目录下输入以下指令:

javah -jni com.aliencat.javabase.jni.HelloJni

即可生成一个一个头文件com_aliencat_javabase_jni_HelloJni.h,内容如下:

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

#ifndef _Included_com_aliencat_javabase_jni_HelloJni
#define _Included_com_aliencat_javabase_jni_HelloJni
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_aliencat_javabase_jni_HelloJni
 * Method:    sayHello
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_aliencat_javabase_jni_HelloJni_sayHello
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

这个h文件相当于我们在java里面的接口,这里声明了一个 Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject);方法,然后在我们的本地方法里面实现这个方法,也就是说我们在编写C/C++程序的时候所使用的方法名必须和这里的一致。

3.编写本地方法实现

本地方法和javah命令生成的头文件里面声明的方法名相同。
代码如下:

#include "jni.h"
#include "HelloJni.h"
//#include other headers
 JNIEXPORT void JNICALL Java_com_aliencat_javabase_jni_HelloJni_sayHello
  (JNIEnv *, jobject, jstring)
{
	printf("Hello world!\n");
	return;
}

注意代码2中的第1行,需要将jni.h(该文件可以在%JAVA_HOME%/include文件夹下面找到)文件引入,因为在程序中的JNIEnv、 jobject等类型都是在该头文件中定义的;另外在第2行需要将HelloWorld.h头文件引入。然后保存为 HelloWorldImpl.c就ok了。打开VC++首先新建一个Win32 Dynamic-Link library工程,之后选择An empty DLL project空工程。把刚刚生成的那个头文件拷贝到这个工程的根目录里。

4.生成动态库

这里以在Windows中为例,需要生成dll文件。在保存HelloWorldImpl.c 文件夹下面,使用VC的编译器cl成。

cl -I%java_home%\include -I%java_home%\include\win32 -LD HelloWorldImp.c -Fehello.dll 注意:生成的dll文件名在选项-Fe后面配置,这里是hello,因为在HelloWorld.java文件中我们loadLibary的时候使用的名字是hello。当然这里修改之后那里也需要修改。另外需要将-I%java_home%\include -I%java_home%\include\win32参数加上,因为在第四步里面编写本地方法的时候引入了jni.h文件。

5.运行程序 java HelloJni.

输出

Hello world

JNI数据类型

Java类型本地类型(JNI)描述
boolean(布尔型)jboolean无符号8比特
byte(字节型)jbyte有符号8比特
char(字符型)jchar无符号16比特
short(短整型)jshort有符号16比特
int(整型)jint有符号32比特
long(长整型)jlong有符号64比特
float(浮点型)jfloat32比特
double(双精度浮点型)jdouble64比特
void(空型)voidN/A

原文链接:https://blog.csdn.net/c15158032319/article/details/117703519



所属网站分类: 技术文章 > 博客

作者:我爱编程

链接:http://www.javaheidong.com/blog/article/222458/ad96e0ee6383b4784df0/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

15 0
收藏该文
已收藏

评论内容:(最多支持255个字符)