首页 > 生活

JNI简介

更新时间:2025-05-26 09:53:00 阅读: 评论:0

准备对JNI开发的知识点做一个总结和分享,大概会介绍如下内容:

JNI 简介JNI 基本类型JNI StringJNI 数组JNI 实例变量JNI 静态变量JNI 回调实例方法与静态方法JNI 调用Java中的super.method()JNI 中创建对象JNI珠宝杂志 中创建对象数组JNI 中局部引用和全局引用JNI 动态注册使用Android NDK编译Android的Native库

后续如无特殊说明JNI相关文章都是基于Java 8。

废话不多说,现在进入正题。

JNI 是什么JNI (Java Native Interface,Java本地接口)是一种编程框架,使得Java虚拟机中的Java程序可以调用本地应用/或库,也可以被其他程序调用。 本地程序一般是用其它语言(C、C++或汇编语言等)编写的,并且被编译为基于本机硬件和操作系统的程序。为什么需要JNI有些事情Java无法处理时,JNI允许程序员用其他编程语言来解决,例如,J人类未解之谜ava标准库不支持的平台相关功能或者程序库。也用于改造已存在的用其它语言写的程序,供Java程序调用。许多基于JNI的标准库提供了很多功能给程序员使用,例如文件I/O、音频相关的功能。当然,也有各种高性能的程序,以及平台相关的API实现,允许所有Java应用程序安全并且平台独立地使用这些功能。

总结起来:

平台相关的功能,通常是为了追求性能,需要对Java虚拟机进行扩展,需要使用Native的实现。Native的实现是已经存在的功能,使用JNI协议,方便使用已有的功能,不需要重新的Java实现。Java的.class文件安全性较差,增加安全性,将重要的逻辑在Native代码中实现。

我们来看一个Hello JNI例子。

Hello JNI

在编程的世界里,第一个程序永远都是Hello World,我们这里来完成一个Hello JNI的例子。

需求

在Java中调用Native方法,Native方法输出Hello JNI。

Java代码

我们先准备Java侧的代码。

// Hello.javapublic class Hello { static { System.loa铁血战士dLibrary("hello"); } public native void sayHello(); public static void main(String[] args) { n计算机硬件工程师ew Hello().sayHello(); }}

首先定义了一个He微淘llo类。

其中的static代码块是JVM在加载类时执行的,System.loadLibrary()表明需要加犬细小载动态库hello,在不同的系统平台上对应不同的名字,在Windows平台上查找的是hello.dll;在Linux平台上查找的是libh散步的侵略者ello.so,而在MacOS平台上查找的是libhello.dylib。

这个库应该被放在Java库的搜索路径中,可以通过-Djava.library.path=/path/to/lib将其加入到搜索路径中。如果路径下没有就爱色找到要导入的库,会在抛出UnsatisfiedLinkError错误。

然后声明了sayHello的native方法,通过native关键字来表明这个方法的实现不在Java中。它的实现应该在hello库中。

最后是我们的测试程序,调用native方法sayHello()。

生成头文件

首先,编译Java程序:

javac Hello.java

生成Hello.class。生成头文件使用javah命令:

javah Hello

生成头文件Hello.h。内容为:

/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class Hello */#结构力学ifndef _Included_Hello#def气调ine _Included_Hello#ifdef __cplusplusextern "C" {#endif/* * Class: Hello * Method: sayHello * Signature: ()V */JNIEXPORT void JNICALL Java_Hello_sayHello (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif

首先,包含的头文件jni.h,它是JDK提供的,位于<JAVA_HOME>/include目录中,以及平台相关的<JAVA_HOME>/include/win32、<JAVA_HOME>/include/linux、<JAVA_HOME>/include/darwin目录下。

接着,这个头文件声明根据Java中的声明的native方法,生成了一个C函数的声明Java_He电脑城llo_sayHello:

JNIEXPORT void JNICALL Java_Hello_sayHello(JNIEnv *, jobject);

Java中的native方法到C函数的命名规则为:

Java_{package_and_classname}_{function_name}();

所有方法以Java_开头,接着是包名比特币大跌和类名,以_替换.,最后是方法名。

在Java中sayHello是没有参数的方法,但是在生成的C函数声明中有两个参数,它们是每个方法都会传递的参数,分别为:

JNIEnv*,指向JNI环境的指针,通过它可以使用JNI协议提供的接口(函数)。jobject,指向this的指针,用于获取类相关的信息(变量、方法等)。

对于JNIEXPORT和JNICALL两个宏,用于设置函数可见性,以及调用栈约定,这里可以忽略这两个宏。

实现native方法

在hello香奈儿老佛爷.c中来实现函数Java_Hello_sayHello

#include 凯乐石登山鞋4;Hello.h"#include <jni.h>#include <stdio.h>JNIEXPORT void JNICALL Java_Hello_sayHello (JNIEnv *env, jobject obj) { printf("Hello JNI!\n");}不同平台编译

在不同的平台上编译方法有所区别。

Linux平台gcc -shared -I$JAVA_HOME/include -I$JAVA_HOME/include/linux Hello.c -o libhello.so

编译生成libhello.so。

Windows平台gcc -Wl,--add-stdcall-alias -shared -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" Hello.c -o hello.dll

编译生成hello.dll。

Macos平台gcc -shared -I$JAVA_HOME/include -I$JAVA_HOME/include/darwin Hello.c -o libhello.dylib

编译生成libhello.dylib。

运行Java程序java -Djava.library.path=. Hello

或者

java Hello

因为我们编译生成的库文件,是在当前目录,可以不指定库查找目录,当前目录默认为库查找目录。

输出Hello JNI!。

至此, 我们已经走通了从Java调用native的路径。

使用C++实现

相比较于C的实现,C++区别不大,将实现的文件由Hello.c命名为Hello.cc,内容为:

#include "Hello.h"#include <jni.h>#include <iostream>JNIEXPORT void JNICALL Java_Hello_sayHello (JNIEnv *env, jobject obj) { std::cout << "Hello JNI fro许纪霖m C++!" << std::endl;}编译

这里以Macos平台为例:

g++ -shared -I$JAVA_HOME/include -I$JAVA_HOME/include/darwin Hello.cc -o libhello.dylib

其他步骤与C的实现一致。

带包名以及分目录的情况

在项目的开发过程中,往往不同类型的文件会存放的不同的目录,而且Java的开发人员和native的人员一般也不是同一个人,所以需要对工程进行一定的组织。

前提条件

假设以下面的目录结构进行组织:

.|-- build|-- jni|-- lib`-- srcbuild目录用于存放编译Java生成的class的目录。jni目录用于存放头文件以及native实现文件。lib目录用于存裁判文书网放native代码编译生成的库文件。src目录用于存放Java源代码的目录。编码

Java源码src/com/furzoom/Hello.java:

package com.furzoom;public class Hello { static { 歌舞伎 System.loadLibrary("hello"); } public native void sayHello(); public static void main(St鬓角ring[] args) { new Hello().sayHello(); }}

编译并生成头文件:

javac -d build src/com/furzoom/Hello做鱼.javajavah -d jni -cp build com.furzoom.Hello

在jni下生成com_furzoom_Hello.h, 内容为:

/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_furzoom_Hello */#ifndef _Included_com_furzoom_Hello#define _Included_com_furzoom_Hello#ifdef __cplusplusextern "C" {#endif/* * Class: com_furzoom_Hello * Method: sayHello * Signature: ()V */JNIEXPORT void JNICALL Java_com_furzoom_Hello_sayHello (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif

文件的名字以及生成C函数签名也上面讲到的规则一致。

C的实现代码jni/hello.c

#include "com_furzoom爱情是什么_Hello.h"#include <jni.h>#include <stdio.h>JNIEXPORT void JNICALL Java_com_furzoom_Hello_sayHello(JNIEnv *env, jobject obj) { printf("Hello JNI!\n");}

编译库文件,这里以Macos为例:

gcc -shared -I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin -Ijni jni/Hello.c -o lib/libhello.dylib

运行Java程序:

java -Djava.library.path=lib -cp build com.furzoom.Hello

输出:

Hello JNI!使用编译器进行开发

使用IntelliJ IDEA和CLion开发JNI环境搭建

微信搜:极客Furzoom,关注获取第一手资料。

本文完。

本文发布于:2023-06-02 07:51:59,感谢您对本站的认可!

本文链接:http://www.ranqi119.com/ge/85/188140.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:简介   JNI
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 站长QQ:55-9-10-26|友情:优美诗词|电脑我帮您|扬州装修|369文学|学编程|软件玩家|水木编程|编程频道