linux java jni_Jni教程(一)—Linux下jni调用

  • Post author:
  • Post category:java


简介

开发环境

代码结构

.h文件生成

编译生成so文件

运行

扩展(有包名的情况)

开发环境

centos 6.8 ×64

[root@localhost jni]# cat /proc/version

Linux version 2.6.32-696.10.2.el6.x86_64 (mockbuild@c1bl.rdu2.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-18) (GCC) ) #1 SMP Tue Sep 12 14:33:29 UTC 2017

jdk 1.8

目录 /usr/local/java/jdk1.8.0_144

[root@localhost jni]# java -version

java version “1.8.0_144”

Java(TM) SE Runtime Environment (build 1.8.0_144-b01)

Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)

g++ 4.4.7

[root@localhost jdk1.8.0_144]# g++ –version

g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-18)

Copyright © 2010 Free Software Foundation, Inc.

本程序是自由软件;请参看源代码的版权声明。本软件没有任何担保;

包括没有适销性和某一专用目的下的适用性担保。

代码结构

为了方便大家能够快速入门,先写一个简单的示例来演示。

先看下代码结构:

e175d5417e05

1.png

JavaMain.java java源代码

CppLib.cpp C++源代码

JavaMain.h 是由JavaMain.java生成的头文件

.h文件生成

public class JavaMain{

public static void main(String[] args){

System.out.println(“Ok!”);

new JavaMain().show();

}

public native void show();

static{

System.loadLibrary(“cpp”);

}

}

代码很简单,native来声明该方法非java方法。static代码块来加载动态库。

接下来就是生成.h文件。直接执行

javah JavaMain.java

生成JavaMain.h头文件

/* DO NOT EDIT THIS FILE – it is machine generated */

#include

/* Header for class JavaMain */

#ifndef _Included_JavaMain

#define _Included_JavaMain

#ifdef __cplusplus

extern “C” {

#endif

/*

* Class: JavaMain

* Method: show

* Signature: ()V

*/

JNIEXPORT void JNICALL Java_JavaMain_show

(JNIEnv *, jobject);

#ifdef __cplusplus

}

#endif

#endif

编译生成so文件

接下来就是引入头文件进行C/C++编码。

#include “JavaMain.h”

#include “jni.h”

JNIEXPORT void JNICALL Java_JavaMain_show

(JNIEnv * env, jobject jb){

printf(“%s”,”cpp library\n”);

}

内容很简单,就是打印一句话。

接下来就是编译,为了方便,我们使用make工具来执行编译过程。这里需要编写Makefile。对Makefile不熟的兄弟可以参考Makefile文件编写。对g++不熟的兄弟可以参考gcc编译参数

libcpp.so : CppLib.cpp

g++ -o $@ $+ -fPIC -shared -I/usr/local/java/jdk1.8.0_144/include -I/usr/local/java/jdk1.8.0_144/include/linux

.PHONY : clean

clean :

-rm libcpp.so

这里主要有几个参数需要注意

-fPIC -shared代表编译成动态库

-I/usr/local/java/jdk1.8.0_144/include -I/usr/local/java/jdk1.8.0_144/include/linux引入jni相关的头文件。我的jdk就安装在/usr/local/java/jdk1.8.0_144下

接下来就是编译,直接执行make命令,成功生成libcpp.so文件。linux下库文件有个特点就是固定以lib开头,.so为扩展名。

运行

得到so文件后,接下来就编译JavaMain.java。执行

javac JavaMain.java

得到JavaMain.class

执行:

java -Djava.library.path=’.’ JavaMain

java一般使用两个path:classpath 和 java.library.path

classpath是指向jar包的位置

java.library.path是非java类包的位置如(dll,so)

结果:

[root@localhost jni]# java -Djava.library.path=’.’ JavaMain

Ok!

cpp library

扩展(有包名的情况)

有不少兄弟在正常的项目开发中,javah和java命令会出现各种错误,比如”找不到**类”。这里我就做一个完整的示例。

e175d5417e05

2.png

有以下几点需要注意:

执行javah和java命令要在源码目录下,也就是src/java目录下。

执行java命令来运行时候,需要制定java.library.path的路径。

/**

* 在java目录下

*

* 生成头文件

* javah com.eric.demo.JavaMain

*

* 编译

* javac com.eric.demo.JavaMain.java

*

* 运行

* java com.eric.demo.JavaMain -Djava.library.path=/code/jni2/src/main/jni

*/



版权声明:本文为weixin_31301881原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。