zoukankan      html  css  js  c++  java
  • 在Java中调用C

    在Java代码中通过JNI调用C函数的步骤如下:

    第一步:编写Java代码

    第二步:编译Java代码(javac Java文件)

    第三步:生成C代码头文件(javah java类名,自动生成)

    第四步:编写C代码(实现C代码头文件里面的函数)

    第五步:生成C共享库(使用工具编译生成C共享库,win下面为dll文件,Linux下面为so文件)

    第六步:运行Java程序(java 类名)

    一、编写Java代码

    首先编写调用C语言的Java源代码HelloJNI.java

    public class HelloJNI {
    native void printHello();
    
    native void printString(String str);
    
    static {
    System.loadLibrary("hellojni");
    }
    
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    HelloJNI myJNI = new HelloJNI();
    myJNI.printHello();
    myJNI.printString("Hello world form printString function!");
    }
    }
    

    说明:

    1. 在Java类中,使用”native”关键字,声明本地方法,该方法与用C/C++编写的JNI本地函数相对应。”native”关键字告知Java编译器,在Java代码中带有该关键字的方法只是声明,具体由C/C++等其它语言编写实现。

    2. 在Java类中声明了本地方法之后,接下来,调用System.loadLibrary()方法,加载具体实现本地方法的C运行库(在Java中加载本地运行库通常使用静态块(static block))。System.loadLibrary()方法加载由字符串参数指定的本地库,在不同操作系统平台下,加载的C运行库不同。在Window下面,调用System.loadLibrary(“hellojni”),则hellojni.dll会被加载;在Linux下面,则会加载libhellojni.so文件。

    二、编译Java代码

    使用javac编译java源代码

    javac HelloJNI.java
    

    三、生成C代码头文件

    使用javah自动生成C代码头文件

    javah HelloJNI
    

    生成的头文件HelloJNI.h见下:

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class HelloJNI */
    
    #ifndef _Included_HelloJNI
    #define _Included_HelloJNI
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
    * Class: HelloJNI
    * Method: printHello
    * Signature: ()V
    */
    JNIEXPORT void JNICALL Java_HelloJNI_printHello
    (JNIEnv *, jobject);
    
    /*
    * Class: HelloJNI
    * Method: printString
    * Signature: (Ljava/lang/String;)V
    */
    JNIEXPORT void JNICALL Java_HelloJNI_printString
    (JNIEnv *, jobject, jstring);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    

    四、编写C代码

    实现C头文件中的方法,hellojni.c文件见下:

    #include "HelloJNI.h"
    #include <stdio.h>
    JNIEXPORT void JNICALL Java_HelloJNI_printHello(JNIEnv *env, jobject obj)
    {
    printf("Hello world!
    ");
    return ;
    }
    
    JNIEXPORT void JNICALL Java_HelloJNI_printString(JNIEnv *env, jobject obj, jstring string)
    {
    const char * str = (*env)->GetStringUTFChars(env,string,0);
    printf("%s!
    ",str);
    return ;
    }
    

    说明:

    1、GetStringUTFChars ()是JNI函数,用来将Java字符串转换成C语言字符串。JNI提供了多种JNI函数,用来处理C字符串与Java字符串的转换,具体参见http://blog.csdn.net/qinjuning/article/details/7595104

    五、生成C共享库

    在Linux下测试,书写makefile文件,编译刚才所写的C代码,生成.so文件;

    makefile文件见下:

    libhellojni.so:hellojni.o makefile
    gcc -Wall -rdynamic -shared -o libhellojni.so hellojni.o
    hellojni.o:hellojni.c HelloJNI.h
    gcc -Wall -c hellojni.c -I./ -I/usr/lib/jdk/include -I/usr/lib/jdk/include/linux -fPIC
    cl:
    rm -rf *.o *.so
    

    使用make命令编译

    make
    

    说明:

    1、生成的so文件必须命令为libhellojni.so,与java代码中的System.loadLibrary("hellojni")对应;

    2、在编译时,必须加上-fPIC,否则,编译时报以下错误:

    /usr/bin/ld: hellojni.o: relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
    hellojni.o: could not read symbols: Bad value
    collect2: ld 返回 1
    make: *** [hellojni.so] 错误 1

    3、gcc和rm前面必须是一个tab空格,否则makefile格式不正确;

    六、运行java程序

    在运行java程序之前,要把生成的so文件加入LD_LIBRARY_PATH中,如下:

    export LD_LIBRARY_PATH=./
    

    否则,在运行java程序的时候报错,错误信息见下:

    Exception in thread "main" java.lang.UnsatisfiedLinkError: no hellojni in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1738)
    at java.lang.Runtime.loadLibrary0(Runtime.java:823)
    at java.lang.System.loadLibrary(System.java:1028)
    at HelloJNI.<clinit>(HelloJNI.java:7)
    Could not find the main class: HelloJNI. Program will exit.
    

    运行java程序:

    java HelloJNI
    

    结果见下:

    Hello world!
    Hello world form printString function!!
  • 相关阅读:
    Ansible facts
    K8S基础概念
    Ansible CMDB
    Docker 核心技术与实现原理
    如何在 Centos7 中使用阿里云的yum源
    一篇文全面了解DevOps:从概念、关键问题、兴起到实现需求
    关于操作stream流
    service not available now, maybe disk full, CL: 0.95 CQ: 0.95 INDEX: 0.95, maybe your broker mach
    AOP的底层实现,动态代理和cglib代理
    模拟浏览器加载静态资源
  • 原文地址:https://www.cnblogs.com/Cherise/p/4350810.html
Copyright © 2011-2022 走看看