Linux下java使用JNI调用C++

Linux下java使用JNI调用C++

1.JNI介绍

JNI即Java Native Interface(Java本地接口),是一个协议,主要作用为:实现Java调用c/c++代码(类库),或者C/C++调用Java代码

2.准备JNI

先用javah,根据.java文件生成.h头文件,然后用C++实现这个接口

2.1先在目录下创建JNI.java文件

内容如下

//JNI.java文件
public class JNI{
   //创建一个native接口方法,此方法在C++代码中实现
   public native int doSomething();
   //静态代码块,加载由C++代码生成的.dll动态链接文件(.dll相当于Java中的jar包吧...)
   static{
       System.loadLibrary("JNIDLL");
   }
}

2.2使用javac编译JNI.java生成JNI.class,然后使用javah编译JNI.class得到JNI.h文件,步骤如下

  • javac编译
    javac JNI.java
  • javah编译JNI.class(不用带后缀名)
    javah JNI
  • 打开JNI.h查看
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JNI */

#ifndef _Included_JNI
#define _Included_JNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     JNI
 * Method:    doSomething
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_JNI_doSomething
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

2.3编写C++代码(JNIDLL.cpp)实现JNI.java中的doSomething()方法(native修饰)

注意方法名是JNI.h中的Java_JNI_doSomething

//JNIdll.cpp文件

#include<stdio.h>
#include<jni.h>
#include "JNI.h"

JNIEXPORT jint JNICALL Java_JNI_doSomething
  (JNIEnv *, jobject){
      //实现代码
      int i = 777;
	  printf("in doSomething \n");
      return i;
}

2.4使用g++编译器生成.so动态库文件

命令如下:
我的jdk路径和你们的不一样,使用的时候要修改一下

g++ -I /java_android/jdk1.8.0_131/include -I  /java_android/jdk1.8.0_131/include/linux/  -fPIC -shared -o libJNIDLL.so JNIDLL.cpp 

也可以将jni.h和jni_md.h拷贝到当前目录下,然后编译:
两个文件在jdk1.8.0_131/include和jdk1.8.0_131/include/linux/下

g++  -fPIC -shared -o libJNIDLL.so JNIDLL.cpp 

3.使用JNI

在java主程序中调用上面准备好的JNI文件

3.1 编写主程序HelloWorld.java文件

//HelloWorld.java文件
import java.lang.Thread;
import java.util.Scanner;

public class HelloWorld {
    public static void main(String []args) {
        System.out.println("Hello World");
		//创建JNI的对象call
        JNI jni = new JNI();
        int count =1;
        while (true)
        {
			try {
        		Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			//调用call()方法;
			int i = jni.doSomething();
        	System.out.println("第 " + count + " 次 sleep 2s "); 
            count++;
	}
   }
}

3.2编译和运行

  • 编译
    javac HelloWorld.java
  • 运行
    java HelloWorld

4.完整过程

virtual-machine:~/codeTest/javaTest$ ll
-rw-rw-r--  1 tsh tsh  534 Mar 29 17:03 HelloWorld.java
-rw-rw-r--  1 tsh tsh  229 Mar 29 17:07 JNIDLL.cpp
-rw-rw-r--  1 tsh tsh  309 Apr  1 11:14 JNI.java
virtual-machine:~/codeTest/javaTest$ javac JNI.java 
virtual-machine:~/codeTest/javaTest$ javah JNI
virtual-machine:~/codeTest/javaTest$ ll
-rw-rw-r--  1 tsh tsh  534 Mar 29 17:03 HelloWorld.java
-rw-rw-r--  1 tsh tsh  349 Apr  1 14:43 JNI.class
-rw-rw-r--  1 tsh tsh  229 Mar 29 17:07 JNIDLL.cpp
-rw-rw-r--  1 tsh tsh  354 Apr  1 14:44 JNI.h
-rw-rw-r--  1 tsh tsh  309 Apr  1 11:14 JNI.java
virtual-machine:~/codeTest/javaTest$ g++ -I /java_android/jdk1.8.0_131/include -I  /java_android/jdk1.8.0_131/include/linux/  -fPIC -shared -o libJNIDLL.so JNIDLL.cpp 
virtual-machine:~/codeTest/javaTest$ ll
-rw-rw-r--  1 tsh tsh  534 Mar 29 17:03 HelloWorld.java
-rw-rw-r--  1 tsh tsh  349 Apr  1 14:43 JNI.class
-rw-rw-r--  1 tsh tsh  229 Mar 29 17:07 JNIDLL.cpp
-rw-rw-r--  1 tsh tsh  354 Apr  1 14:44 JNI.h
-rw-rw-r--  1 tsh tsh  309 Apr  1 11:14 JNI.java
-rwxrwxr-x  1 tsh tsh 8136 Apr  1 14:46 libJNIDLL.so*
virtual-machine:~/codeTest/javaTest$ javac HelloWorld.java 
virtual-machine:~/codeTest/javaTest$ ll
-rw-rw-r--  1 tsh tsh  955 Apr  1 14:46 HelloWorld.class
-rw-rw-r--  1 tsh tsh  534 Mar 29 17:03 HelloWorld.java
-rw-rw-r--  1 tsh tsh  349 Apr  1 14:43 JNI.class
-rw-rw-r--  1 tsh tsh  229 Mar 29 17:07 JNIDLL.cpp
-rw-rw-r--  1 tsh tsh  354 Apr  1 14:44 JNI.h
-rw-rw-r--  1 tsh tsh  309 Apr  1 11:14 JNI.java
-rwxrwxr-x  1 tsh tsh 8136 Apr  1 14:46 libJNIDLL.so*
virtual-machine:~/codeTest/javaTest$ java HelloWorld 
Hello World
in doSomething 
第 1 次 sleep 2s 
in doSomething 
第 2 次 sleep 2s 
in doSomething 
第 3 次 sleep 2s 

5.参考

错误排查参考
windows下使用JNI

猜你喜欢

转载自blog.csdn.net/tsh123321/article/details/88948675