前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Jni教程(一)—Linux下jni调用简介

Jni教程(一)—Linux下jni调用简介

作者头像
用户2929716
发布2018-08-23 13:31:57
2.1K0
发布2018-08-23 13:31:57
举报
文章被收录于专栏:流媒体流媒体

简介

  • 开发环境
  • 代码结构
  • .h文件生成
  • 编译生成so文件
  • 运行
  • 扩展(有包名的情况)

开发环境

  • centos 6.8 ×64
代码语言:javascript
复制
[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
代码语言:javascript
复制
[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
代码语言:javascript
复制
[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.
本程序是自由软件;请参看源代码的版权声明。本软件没有任何担保;
包括没有适销性和某一专用目的下的适用性担保。

代码结构

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

先看下代码结构:

1.png

  • JavaMain.java java源代码
  • CppLib.cpp C++源代码
  • JavaMain.h 是由JavaMain.java生成的头文件

.h文件生成

代码语言:javascript
复制
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文件。直接执行

代码语言:javascript
复制
javah JavaMain.java

生成JavaMain.h头文件

代码语言:javascript
复制
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* 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++编码。

代码语言:javascript
复制
#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编译参数

代码语言:javascript
复制
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。执行

代码语言:javascript
复制
javac JavaMain.java

得到JavaMain.class

执行:

代码语言:javascript
复制
java -Djava.library.path='.' JavaMain

java一般使用两个path:classpath 和 java.library.path classpath是指向jar包的位置 java.library.path是非java类包的位置如(dll,so)

结果:

代码语言:javascript
复制
[root@localhost jni]# java -Djava.library.path='.' JavaMain
Ok!
cpp library

扩展(有包名的情况)

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

2.png

有以下几点需要注意:

  • 执行javah和java命令要在源码目录下,也就是src/java目录下。
  • 执行java命令来运行时候,需要制定java.library.path的路径。
代码语言:javascript
复制
/**
* 在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
*/
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017.10.23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
    • 开发环境
      • 代码结构
        • .h文件生成
          • 编译生成so文件
            • 运行
              • 扩展(有包名的情况)
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档