zoukankan      html  css  js  c++  java
  • Java 调用C语言JNI库(Hello World实例)

    要在java中调用c语言的库,一直觉得很不可思议,但是Java提供了JNI这个东西,这也就变得可能了. 作为一个码农,我们还是从最简单的 Hello World开始吧.

    首先说一下我们想要做的事情. 在c语言中定义一个 void sayHello()函数(打印Hello World);然后在Java中调用这个函数显示Hello Word.

    现在分别从Java和C语言两部分说明:

    1. Java  部分

      我们首先定义一个HelloNative,在其中申明sayHello函数,函数要申明为Native 类型的.如下:

    public class HelloNative {
        public native void sayHello();
    }

    编译这个类,生成class文件:

    javac HelloWorld.java

    利用javah生成需要的h文件

    javah HelloNative

    生成的 h文件大概如下:

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class HelloNative */
    
    #ifndef _Included_HelloNative
    #define _Included_HelloNative
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     HelloNative
     * Method:    sayHello
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_HelloNative_sayHello
      (JNIEnv *, jobject);
    
    #ifdef __cplusplus
    }
    #endif
    #endif

    我们可以看一下上面自动生成的程序,程序include了jni.h,这个头文件在 $JAVA_HOME下的include文件夹下. 还可以发现生成的函数名是在我们的函数名前面加上了Java_HelloNative.

    2. C语言部分

      根据上面生成的h文件编写相应的代码实现,如我们建立一个 HelloNative.cpp用来实现显示Hello World的函数.如下:

    #include <stdio.h>
    #include "HelloNative.h"
    
    JNIEXPORT void JNICALL Java_HelloNative_sayHello(JNIEnv *, jobject)
    {
        printf("Hello World!\n");
    }

    代码编写完成之后,我们再用gcc编译成库文件,命令如下;

    gcc -fPIC -I/usr/lib/jvm/java-7-openjdk-i386/include -I/usr/lib/jvm/java-7-openjdk-i386/include/linux -shared -o libHelloNative.so HelloNative.cpp 

    这样就会在当前目录下生成一个libHelloNative.so的库文件.这时我们需要的库已经生成,在C语言下的工作已经完成了.

    接下来我们需要在Java中编写一个程序测试一下.在程序前,我们需要将我们的库载入进去.载入的方法是调用Java的 System.loadLibrary("HelloNative"); 

    public class TestNative 
    {
        static {
            try { 
                System.loadLibrary("HelloNative"); 
            } 
            catch(UnsatisfiedLinkError e) { 
                System.out.println( "Cannot load hello library:\n " + e.toString() ); 
            }
        }
        public static void main(String[] args) {
            HelloNative test = new HelloNative();
            test.sayHello();
        }
    }

    但是再我们编译后,运行的时候,问题又出现了.

    Cannot load hello library:
     java.lang.UnsatisfiedLinkError: no HelloNative in java.library.path
    Exception in thread "main" java.lang.UnsatisfiedLinkError: HelloNative.sayHello()V
        at HelloNative.sayHello(Native Method)
        at TestNative.main(TestNative.java:13)

    载入库失败,但是我们的库明明就是放在当前文件夹下的,怎么会载入失败呢?

    我们用System.getProperty("java.library.path")查看,发现java.library.path中并不u存在当前的目录.主要有以下的几个解决办法:

    1) 将生成的库复制到java.library.path有的路径中去,当然这样不是很好

    2) 设置环境变量export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ,将当前的目录加入到LD_LIBRARY_PATH中

    3) 设置java 的选项,将当前的目录加入到其中 .java -Djava.library.path=. $LD_LIBRARY_PATH

    这样之后我们的程序就能够成功的运行了.可以看见显示的"Hello World!"了

      

  • 相关阅读:
    创建用户中遇到的问题
    创建用户和用户组
    ActiveMq在linxu系统上的启动
    CentOs 6.5 安装jdk
    卸载CentOs6.5自带的OpenJDK
    centos 6.5 添加ip地址
    CentOs 6.5的安装
    jna的简单测试
    电脑硬盘空间怎么越来越小
    build path contains duplicate entry:'src' for project 'XXX'
  • 原文地址:https://www.cnblogs.com/lovesaber/p/2993375.html
Copyright © 2011-2022 走看看