`

Linux平台使用JNI Java调用so

    博客分类:
  • java
 
阅读更多

在做一个医疗设备的项目的时候由于涉及到心电图数据的解析,因为解析只能依靠c,所以需要java调用c生成的动态库去解析数据。
    因为用JNI调用Linux下的动态库,要求java类名和动态库中的名保持一致,所以只能通过生成一个libFileUtil.so去调用客户提供的libauto_analyse.so。

1. 确保gcc编译器已安装
2. 编写FileUtil.java 代码,用native声明需要用c实现的函数。
如果源程序是包含在package的话,应该建立同样的文件夹结构,如com/hnrbyl/rmas/util/FileUtil.java

	package com.hnrbyl.rmas.util;

public class FileUtil {
	public native static String ResultText(); 
	public static void main(String[] args) {
		System.loadLibrary("FileUtil");
		String s=FileUtil.ResultText();
		System.out.println(s);
	}

}


项目中的代码:

public class FileUtil {  
        //要调用.so中的方法  
    public native static String ResultText(String txtPath, String pdfPath);   
  
    public static String autoAnalyse(String txtPath, String pdfPath){  
        //加载自动分析已上传心电图的动态链接库文件  
        System.loadLibrary("FileUtil");  
        String jsonData = FileUtil.ResultText(txtPath, pdfPath);  
        return jsonData;  
    }  
} 


3. 在FileUtil.java文件所在目录下编译.java文件
Javac FileUtil.java

4. 编译第三步生成的.class文件,生成对应的.h头文件,本例中生成com_hnrbyl_rmas_util_FileUtil
Javah –classpath  ~workspace\elect\WebRoot\WEB-INF\classes -d d:\ -jni com.hnrbyl.rmas.util.FileUtil

其中java中各个命令的意思
-classpath <路径> 用于转入类的路径
-d <目录> 输出目录
-jni 生成JNI样式的头文件(默认)

这个Java文件是在路径“E:\workspace\elect\src”下,包“package com.hnrbyl.rmas.util;”中的
得到的FileUtil 对应的class文件,在路径“E:\workspace\elect\WebRoot\WEB-INF\classes\com\hnrbyl\rmas\util”下。

注意到以上我们命令中指定的路径
注意到我们的命令符的执行位置是源代码目录” E:\workspace\elect\src\”
-classpath  后面的路径是指包” com.hnrbyl.rmas.util”所在的根路径(如下图所示)


 

5. 第四部中生成的头文件内容

/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class FileUtil */

#ifndef _Included_com_hnrbyl_rmas_util_FileUtil
#define _Included_com_hnrbyl_rmas_util_FileUtil
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     FileUtil
* Method:    ResultText
* Signature: (I)I
*/
	JNIEXPORT jstring JNICALL Java_com_hnrbyl_rmas_util_FileUtil_ResultText(JNIEnv*,
	        jobject);


#ifdef __cplusplus
}
#endif
#endif


项目中的代码:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class FileUtil */

#ifndef _Included_com_hnrbyl_rmas_util_FileUtil
#define _Included_com_hnrbyl_rmas_util_FileUtil
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_hnrbyl_rmas_util_FileUtil
 * Method:    ResultText
 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_hnrbyl_rmas_util_FileUtil_ResultText
  (JNIEnv *, jclass, jstring, jstring);


#ifdef __cplusplus
}
#endif
#endif



6. 编写FileUtil.c文件,实现引用第4步中生成的.h头文件,并声明其中的方法。


#include "jni.h"
#include "stdlib.h"
#include "FileUtil.h"
//
JNIEXPORT jstring JNICALL  Java_com_hnrbyl_rmas_util_FileUtil_ResultText(JNIEnv *env,
	jobject obj) 
	{
	char* str = "Hello World!"; 
	jstring rtn;
	rtn = env->NewStringUTF(str);
	return rtn;
	}


项目中的代码:

#include "stdlib.h"
#include "stdio.h"
#include "FileUtil.h"
#include "dlfcn.h"
#include "jni.h"
JNIEXPORT jstring JNICALL  Java_com_hnrbyl_rmas_util_FileUtil_ResultText
  (JNIEnv *env,	jobject obj, jstring txtPath, jstring pdfPath) 
	{
	   char** (*myso)(char* a, char* b);//function pointer   
	   void *handle; 
	   char *errorInfo;
	   handle=dlopen("libauto_analyse.so",RTLD_LAZY);//open lib file   
	   errorInfo = dlerror();
	   // 如果返回 NULL 句柄,表示无法找到对象文件,过程结束。否则的话,将会得到对象的一个句柄,可以进一步询问对象
	   if (errorInfo){
           // 如果返回 NULL 句柄,通过dlerror方法可以取得无法访问对象的原因
           printf("Open Error:%s.\n",dlerror());
           return 0;
	   }
	   // 使用 dlsym 函数,尝试解析新打开的对象文件中的符号。您将会得到一个有效的指向该符号的指针,或者是得到一个 NULL 并返回一个错误
	   myso=dlsym(handle,"auto_analyse");//call dlsym function  
	   errorInfo = dlerror();// 调用dlerror方法,返回错误信息的同时,内存中的错误信息被清空	   
	   if (errorInfo){
           printf("Dlsym Error:%s.\n",errorInfo);
           return 1;
       }
	   char* a=(*env)->GetStringUTFChars(env, txtPath, 0);
	   char* b=(*env)->GetStringUTFChars(env, pdfPath, 0);
	   char **str=(*myso)(a,b);   
	   dlclose(handle);  
	   (*env)->ReleaseStringUTFChars(env, txtPath, a);
	   (*env)->ReleaseStringUTFChars(env, pdfPath, b);
	   jstring rtn;
	   rtn = (*env)->NewStringUTF(env,str[1]);
	   return rtn;
	}



7. 讲第6步中编写的FileUtil.c文件,编译成.so文件
gcc -I/wenjin/jdk1.7.0_25/include/ -I/wenjin/jdk1.7.0_25/include/linux/ -fPIC -shared -o libFileUtil.so FileUtil.c
注:/ wenjin/jdk1.7.0_25/include 是jni.h头文件所在的路径
/ wenjin/jdk1.7.0_25/include/linux 是jni_md.h所在的路径

8. 将第7步中生成的libFileUtil.so文件拷贝到java的加载库LD_LIBRARY_PATH指向的路径中。
9. 在运行FileUtil.class
在com.hnrbyl.rmas.util跟目录src下运行
Java com.hnrbyl.rmas.util.FileUtil

一切正常后,可以看到运行結果是输出了Hello World!,其值是由C语言代码实现并返回的。






gcc -I/usr/java/jdk1.7.0_25/include/ -I/usr/java/jdk1.7.0_25/include/linux/ -lauto_analyse -lhpdf -lz -lm -ljson-c -fPIC -shared -o libFileUtil.so FileUtil.c

执行该句的问题。
问题:
/usr/bin/ld: /usr/local/lib/libz.a(crc32.o): relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
/usr/local/lib/libz.a: could not read symbols: Bad value
一般是64 位 电脑才会出现。

解决方法如下:
cd zlib-1.2.3 //进入zlib目录

CFLAGS="-O3 -fPIC" ./configure   //使用64位元的方法进行编译

make

make install

make clean

 

  • 大小: 75.6 KB
分享到:
评论

相关推荐

    在windows中jni(生成dll)Linux中jni(生成so),java调用曾c++

    1. **Java调用C++的基本原理** - JNI为Java应用程序提供了一个桥梁,可以调用本地代码(如C++),反之亦然。这使得开发者可以在必要时利用C++的性能优势或者调用系统级API。 - Java程序通过`System.loadLibrary`或...

    linux C JNI调用java

    本资源详细介绍了如何在Linux环境中通过C语言使用JNI调用Java类的函数,以下是对这个主题的详细阐述。 首先,要进行C语言调用Java类,我们需要确保有Java Development Kit (JDK) 安装并正确配置。JDK包含了一系列...

    Java JNI调用动态库(Linux、Windows)的实现步骤

    本篇文档将详细介绍如何在 Linux 和 Windows 平台上使用 Java 调用动态链接库(DLL 在 Windows 上称为 .dll 文件,在 Linux 上称为 .so 文件)。这通常涉及到三个主要步骤:编写 Java 接口、定义 C/C++ 头文件和实现...

    java调用C语言编写的so库中的函数,java调用C语言编写的dll库中的函数

    总的来说,Java调用C语言编写的本地库需要理解JNI和JNA的工作原理,以及它们如何处理数据类型转换、参数传递和本地库的加载。通过这些技术,开发者可以充分利用C/C++的性能优势,同时享受Java的平台独立性和高级抽象...

    springboot+jna/jni调用动态so/dll库

    "springboot+jna/jni调用动态so/dll库"是一个重要的主题,它涉及到Spring Boot应用如何利用Java Native Interface (JNI) 和 Java Native Access (JNA) 这两种技术来调用操作系统级别的动态链接库(.so for Linux, ....

    使用C++创建java虚拟机JVM,使用JNI调用java函数.zip

    本文将深入探讨如何使用C++创建Java虚拟机(JVM),并通过JNI来调用Java函数。这是一项技术性很强的任务,需要对C++编程、Java虚拟机的工作原理以及JNI接口有深入的理解。 首先,Java虚拟机(JVM)是Java平台的核心...

    linux-java调用c语言编译的so动态库-jni例子-简单计算器

    这个"linux-java调用c语言编译的so动态库-jni例子-简单计算器"是一个典型的示例,展示了如何利用JNI来创建一个Java应用程序,该程序能够调用C编写的动态链接库(.so文件)进行计算操作。 JNI是Java平台的一部分,它...

    JNI实现的DEMO Java调用VC编写的DLL,对应于Linux .SO

    标题中的“JNI实现的DEMO Java调用VC编写的DLL,对应于Linux .SO”指的是一个使用Java Native Interface (JNI) 技术的示例,该示例展示了如何在Java程序中调用由Visual C++ (VC) 编译生成的动态链接库(DLL) 文件,...

    C++库封装JNI接口-实现java调用c++

    总结,C++库封装JNI接口实现Java调用C++涉及的主要步骤包括:声明Java中的本地方法,生成JNI头文件,编写C++实现,编译成库,最后在Java中加载并调用。这个过程需要理解Java和C++之间的数据类型转换,以及如何在两种...

    opencv-4.5.5编译后的jar包和linux平台的so文件

    其次,`libopencv_java455.so` 是一个动态链接库文件,它是OpenCV库在Linux平台上的实现。在Linux系统中,`.so` 文件是共享对象(Shared Object),相当于Windows系统中的`.dll` 文件。这个特定的文件是OpenCV的Java...

    java使用JNI调用C++ dll库用法概述

    Java使用JNI(Java Native Interface)调用C++ DLL库是一种常见的技术,特别是在需要利用Java的跨平台特性同时利用C++的高效性能时。JNI提供了一种桥梁,使得Java代码能够直接与本地代码交互,比如C++编译的动态链接...

    使用JNI进行混合编程:在Java中调用C/C++本地库

    - Sample1.cpp和Sample1.h构成了C/C++端的实现,它们将被编译成动态链接库供Java调用。 通过以上步骤,我们可以看到,JNI允许Java和C/C++代码无缝集成,实现了跨语言的混合编程。这不仅扩展了Java的功能,还能利用...

    科大讯飞语音合成示例(离线版本) java可调用 dll so封装

    提供java jni示例程序,linux so工程,windows dll工程,将科大讯飞语音合成程序封装成windows支持的dll和linux支持的so并且导出api,java使用jni直接调用。代码均已编译测试通过,需要appid和mscdll则可以自己去...

    java在Linux下调用sap的RFC接口必备so文件 libsapjco3.so

    Java在Linux环境中调用SAP RFC接口涉及到的关键技术点包括Java与SAP的集成、Linux系统下的动态链接库(.so文件)以及SAP的RFC(远程功能调用)技术。这里将详细介绍这些知识点。 首先,SAP RFC是SAP提供的一种通信...

    java调用c++生成so库

    标题“java调用c++生成so库”指的是在Linux环境下,通过JNI技术,Java程序可以调用预先用C++编译生成的动态链接库(.so文件)。.so文件是Linux下的动态共享对象,相当于Windows下的.DLL文件,它包含了可由多个程序...

    java中RCP中使用JNI

    在Java RCP中使用JNI,主要是为了访问特定于平台的功能,提升性能,或者调用已有的本地库。 1. **JNI简介** JNI是一种接口,允许Java代码与其他语言编写的代码进行通信。它定义了一套规范,使得Java虚拟机(JVM)...

    JNI与Java方法的相互调用

    JNI,全称Java Native Interface,是Java平台标准的一部分,它允许Java代码和其他语言写的代码进行交互。JNI在很多场景下都是必要的,比如访问操作系统特定功能、优化性能关键部分或者集成已有的C/C++库。本笔记主要...

    通过JNI调用第三方动态库(生成两个.so文件)

    在Linux系统(包括Android)中,.so文件是共享库的扩展名,这些库通常包含了C/C++编译的原生代码,它们提供了Java层无法直接访问的低级功能。Android NDK(Native Development Kit)则是一个工具集,允许开发者使用C...

Global site tag (gtag.js) - Google Analytics