创建 Java 项目
  • 系统环境: ubuntu 16.04
  • 开发工具: idea
  • 开发环境: JDK1.8
  • 项目名称: HelloWorldJava

查看java环境变量
mao-siyu@mao-siyu-PC:~cat /etc/profile
export JAVA_HOME=/home/java/jdk1.8.0_111
export CLASSPATH=.:JAVA_HOME/lib/dt.jar:JAVA_HOME/lib/tools.jar
export PATH=JAVA_HOME/bin:PATH
mao-siyu@mao-siyu-PC:~$

最终工程目录结构
HelloWorldJava
    |--`src`
        |--com
            |--blog
                 |--testnative
                         |--MainJNI.java
                         |--MainTest.java
        |--com_blog_testnative_MainJNI.cpp
        |--com_blog_testnative_MainJNI.h
        |--jni.h
        |--jni_md.h
        |--testJNI.so
mao-siyu@mao-siyu-PC:~/IDEAProjects/HelloWorldJava$ pwd
/home/mao-siyu/IDEAProjects/HelloWorldJava

创建 HelloWorldJava 项目工程
将JDK下的 /home/java/jdk1.8.0_111/include/jni.h /home/java/jdk1.8.0_111/include/linux/jni_md.h 复制到src文件夹下备用
创建 MainJNI.java
package com.blog.testnative;

/**
 * 匹配 C++
 * Created by mao-siyu on 17-8-2.
 */
public class MainJNI {

    /**
     * 定义一个规范方法(相当于java与C++的接口), 之后在C++中进行实现
     */
    public native String sayHello();
}

使用 javah命令 生成 MainJNI.h 文件
mao-siyu@mao-siyu-PC:~/IDEAProjects/HelloWorldJava/srcjavah com.blog.testnative.MainJNI
mao-siyu@mao-siyu-PC:~/IDEAProjects/HelloWorldJava/src ll
drwxrwxr-x 3 mao-siyu mao-siyu  4096 8月   2 17:14 ./
drwxrwxr-x 4 mao-siyu mao-siyu  4096 8月   2 17:19 ../
drwxrwxr-x 3 mao-siyu mao-siyu  4096 8月   2 11:37 com/
-rw-rw-r-- 1 mao-siyu mao-siyu   488 8月   2 17:24 com_blog_testnative_MainJNI.h
-rw-r--r-- 1 mao-siyu mao-siyu 73701 8月   2 16:28 jni.h
-rw-r--r-- 1 mao-siyu mao-siyu   824 8月   2 16:29 jni_md.h
mao-siyu@mao-siyu-PC:~/IDEAProjects/HelloWorldJava/srcmao-siyu@mao-siyu-PC:~/IDEAProjects/HelloWorldJava/src cat com_blog_testnative_MainJNI.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class com_blog_testnative_MainJNI */

#ifndef _Included_com_blog_testnative_MainJNI
#define _Included_com_blog_testnative_MainJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_blog_testnative_MainJNI
 * Method:    sayHello
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_blog_testnative_MainJNI_sayHello
  (JNIEnv *env, jobject);

#ifdef __cplusplus
}
#endif
#endif
mao-siyu@mao-siyu-PC:~/IDEAProjects/HelloWorldJava/src$

注意: 需要将#include 改为 #include "jni.h" 引用当前src下的, 这样做生成so文件的脚本 -I 就可以不用指定了.


创建 com_blog_testnative_MainJNI.cpp 文件
#include 
#include "com_blog_testnative_MainJNI.h"

JNIEXPORT jstring JNICALL Java_com_blog_testnative_MainJNI_sayHello (JNIEnv *env, jobject) {
    return env->NewStringUTF("Hello JNI");
}

使用g++ 将.cpp文件 转成.so文件
mao-siyu@mao-siyu-PC:~/IDEAProjects/HelloWorldJava/srcg++ com_blog_testnative_MainJNI.cpp -shared -fPIC -o testJNI.so
mao-siyu@mao-siyu-PC:~/IDEAProjects/HelloWorldJava/src

创建 MainTest.java 用来测试
package com.blog.testnative;

/**
 * Created by mao-siyu on 17-8-2.
 */
public class MainTest {

    /**
     * 引入SO文件
     */
    static {
        String soPath = "/home/mao-siyu/IDEAProjects/HelloWorldJava/src/testJNI.so";
        System.load(soPath);
    }

    public static void main(String[] args) {
        MainJNI mainJNI = new MainJNI();
        System.out.println(mainJNI.sayHello());
    }
}



使用CLion生成.so文件
运行环境
  • 系统环境: ubuntu 16.04
  • 开发工具: CLion
  • 项目类型: C++ Library 这种是开发共享库时使用(本次使用)
  • 项目类型: C++ Executable 这种是开发C++时使用
  • 项目名称: HelloWorldLib
项目工程目录
HelloWorldLib
    |--cmake-build-debug/
    |--CMakeLists.txt
    |--com_blog_testnative_MainJNI.cpp
    |--com_blog_testnative_MainJNI.h
    |--jni.h
    |--jni_md.h
创建项目工程 HelloWorldLib

将IDEA里面的文件复制到这里面进行编译.

修改CMakeLists.txt文件
cmake_minimum_required(VERSION 3.8)
project(HelloWorldLib)

set(CMAKE_CXX_STANDARD 11)

set(SOURCE_FILES jni.h jni_md.h com_blog_testnative_MainJNI.cpp com_blog_testnative_MainJNI.h)
add_library(HelloWorldLib ${SOURCE_FILES})



编译命令解释

编译成共享库, 在Java JNI调用时使用, 不可以直接运行.
g++ com_blog_testnative_MainJNI.cpp -shared -fPIC -o testJNI.so

mao-siyu@mao-siyu-PC:~/CLionProjects/HelloWorldLibg++ com_blog_testnative_MainJNI.cpp -shared -fPIC -o testJNI.so
mao-siyu@mao-siyu-PC:~/CLionProjects/HelloWorldLib ./testJNI.so
段错误 (核心已转储)

编译成可执行文件, 这种编译完后可以直接运行, 但java JNI不能使用.
g++ com_blog_testnative_MainJNI.cpp -ldl -o testJNI.so

mao-siyu@mao-siyu-PC:~/CLionProjects/HelloWorldLibg++ com_blog_testnative_MainJNI.cpp -ldl -o testJNI.so
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:在函数‘_start’中:
(.text+0x20):对‘main’未定义的引用
collect2: error: ld returned 1 exit status
mao-siyu@mao-siyu-PC:~/CLionProjects/HelloWorldLib

因此这条命令执行会报错 它是在 项目类型: C++ Executable 时使用的

下载 HelloWorldJNI.zip

分类: Java

毛巳煜

高级软件开发全栈架构师

工信部备案号:辽ICP备17016257号-2