创建 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 时使用的