JNI-Linux

JNI是Java Native Interface的缩写,Java源生接口/本地调用/本地接口,允许Java和其他语言代码进行互相调用,Java可以调用C/C++代码,C/C++也可以调用Java的。Java程序运行在JVM上,所以平台无关,但通过JNI调用原生代码C/C++就会丧失这个特性,破坏可移植性,至少原生代码部分总是需要重新编译的。但是一下情况是可以接受的。

1.使用一些旧的库

2.与硬件、操作系统进行交互

3.为了提高程序的性能

Note:jni.h就在%JAVA_HOME%\include下,还有%JAVA_HOME%\include\win32下的jni_md.h

Warning:javah在Java10,生成C/C++头文件的功能由javac -h代替

image

编写JAVA类

static代码段的System.load调用,这段代码表示在程序加载的时候,自动加载libHello.so库。
区分一下加载动态库的2种方式
一个概念是JVM有两个重要变量java.class.pathjava.library.path。前者指明了package的路径,后者指明了动态链接库的路径。
System.load();绝对路径
System.loadLibrary ();java.library.path下加载,不需要指明扩展名

public class Hello{

   public native static String sayHello(String name);

   static{
           System.load("/usr/project/test/libHello.so");
         #System.loadLibrary("Hello");
     }

    public static void main(String[] args){
             Hello hello = new Hello();
             String ret = hello.sayHello("Simona");
             System.out.println(ret);
   }
 }

编译JAVA类

javac Hello.java

生成Hello.h

javah -jni Hello
or
javac -h . Hello
Note:JAVA 10弃用了javah

有包名的情况下需要指定classpath,不然会出现UnsatisfiledLinkError

javah -classpath 'your package path' -jni 'package'.Hello
or
指明共享库路径
java -Djava.library.path=. Hello
export LD_LIBRARY_PATH=“Hello路径”:$LD_LIBRARY_PATH

编写Native Method

生成的Hello.h的头文件带有需要实现的Native Method,实现这个Native Method需要指定参数名称
cat Hello.h
vim hello.c
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Hello */

#ifndef _Included_Hello
#define _Included_Hello
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Hello
 * Method:    sayHello
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_Hello_sayHello
  (JNIEnv *, jclass, jstring);

#ifdef __cplusplus
}
#endif
#endif
#include <stdio.h>
#include "Hello.h"

JNIEXPORT jstring JNICALL Java_Hello_sayHello(JNIEnv *env, jclass jc, jstring name)
{
    const char *buf;

    buf = (*env)->GetStringUTFChars(env, name, NULL);
    if (NULL == buf)
    {
        return NULL;
    }

    printf("%s\n", buf);
    
    (*env)->ReleaseStringUTFChars(env, name, buf);

    return (*env)->NewStringUTF(env, "hello");
}

GetStringUTFChars
返回指向字符串的 UTF-8 字符数组的指针,如果不能创建这个字符数组,返回 null。该数组在被ReleaseStringUTFChars()释放前将一直有效
const char* GetStringUTFChars(jstring string,jboolean* isCopy)

NewStringUTF
利用UTF-8字符数组构造新java.lang.String对象
(*env)->NewStringUTF(env, "hello");

制作动态库

由于是Linux平台,需要制作后缀是.so的动态库,其中,需要指定jni.h的路径,必要时还需要jni_md.h的路径,该文件在jdk的目录中。这里指定了jni.h和jni_md.h的路径。
一个库的必须要是:lib+库名+.so。链接的时候只需要提供库名就可以了

find / -name jni.h
/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.221-2.6.18.0.el7_6.x86_64/include/jni.h
find / -name jni_md.h
/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.221-2.6.18.0.el7_6.x86_64/include/linux/jni_md.h

gcc -c -fPIC -I/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.221-2.6.18.0.el7_6.x86_64/include/ -I/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.221-2.6.18.0.el7_6.x86_64/include/linux/ Hello.c -o Hello.o

gcc -shared Hello.o -o libHello.so

调用动态库

java Hello
Simona
hello

出现UnsatisfiedLinkError

pwd
/usr/project/test

export LD_LIBRARY_PATH=/usr/project/test:$LD_LIBRARY_PATH
java Hello
Simona
hello

or

java -Djava.library.path=. Hello
Simona
hello

创建调用类

import java.util.*;
public class HelloJni
{
     public static void main(String argv[])
     {
         System.out.println( System.getProperty("java.library.path"));
         new HelloJni();
     }

     public HelloJni()
     {
         new Hello().sayHello("Hello,Jni !"); //调用Hello的原生函数sayHello
     }
}

执行调用

javac HelloJni.java
java HelloJni
/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
Hello,Jni !

参考网址

JNI编程实现(Linux)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容

  • _ 声明: 对原文格式以及内容做了细微的修改和美化, 主要为了方便阅读和理解 _ 一. 基础 Java Nativ...
    元亨利贞o阅读 5,921评论 0 34
  • *** 说明:本文不代表博主观点,均是由以下资料整理的读书笔记。 *** 【参考资料】 1、向您的Android ...
    莫绪旻_向屿阅读 1,681评论 0 6
  • JNI是什么? JNI的全称就是Java Native Interface,顾名思义,就是Java和C/C++相互...
    hongzhenw阅读 3,507评论 2 15
  • 我是一名普通的人民教师,今天是9月10日——我们的节日。在这个特殊的日子里,我不禁在思考这个节日的价值、意义之所在...
    Joanne_fa80阅读 345评论 0 4
  • 在大漠先生的引领下,我开始了一周碧珠生活智慧的禅绕画之旅,今天做一个小总结。 在这次的小结里,我将大漠先生的智慧语...
    时光分拣机阅读 955评论 1 19