linux下java调用C

 

linux下java调用C

分类: linux
下面是在ubuntu 下java jni调用C语言动态链接库的具体操作步骤。
1、创建一个Java程序(TestJNI.java)定义原生的c函数。
2、用javac编译TestJNI.java生成TestJNI.class。用javah带-jni参数编译TestJNI.class生成TestJNI.h文件,该文件中 定义了c的函数原型。在实现c函数的时候需要。
3、创建Hello.c,实现TestJNI.h定义的函数。
4、编译Hello.c生成libgoodlucky.so。
5、在java虚拟机运行java程序TestJNI。


1、Test.java 源文件

 

[html] view plaincopy
 
  1. public class TestJNI {  
  2.   
  3.     static{  
  4.   
  5.         System.loadLibrary("goodlucky");  
  6.   
  7.     }  
  8.   
  9.     public native void set(int value);  
  10.   
  11.     public native int get();  
  12.   
  13.     public static void main(String[] args) {  
  14.   
  15.         TestJNI td=new TestJNI();  
  16.   
  17.         td.set(10);  
  18.   
  19.         System.out.println(td.get());  
  20.   
  21.     }  
  22.   
  23. }   
 
2、javac TestJNI.java
   javah -jni Test
   生成了TestJNI.h文件
   内容如下:
 
[cpp] view plaincopy
 
  1. /* DO NOT EDIT THIS FILE - it is machine generated */  
  2.         #include <jni.h>  
  3.         /* Header for class TestJNI */  
  4.           
  5.         #ifndef _Included_TestJNI  
  6.         #define _Included_TestJNI  
  7.         #ifdef __cplusplus  
  8.         extern "C" {  
  9.         #endif  
  10.         /* 
  11.          * Class:     TestJNI 
  12.          * Method:    set 
  13.          * Signature: (I)V 
  14.          */  
  15.         JNIEXPORT void JNICALL Java_TestJNI_set  
  16.           (JNIEnv *, jobject, jint);  
  17.           
  18.         /* 
  19.          * Class:     TestJNI 
  20.          * Method:    get 
  21.          * Signature: ()I 
  22.          */  
  23.         JNIEXPORT jint JNICALL Java_TestJNI_get  
  24.           (JNIEnv *, jobject);  
  25.           
  26.         #ifdef __cplusplus  
  27.         }  
  28.         #endif  
  29.         #endif  
 
3、 TestJNI.c,内容如下
 
[cpp] view plaincopy
 
  1. #include <stdio.h>  
  2.     #include "TestJNI.h"  
  3.     int i=0;  
  4.     JNIEXPORT void JNICALL Java_TestJNI_set  
  5.       (JNIEnv * env, jobject obj, jint j)  
  6.     {  
  7.        i=j;  
  8.       
  9.     }  
  10.       
  11.     JNIEXPORT jint JNICALL Java_TestJNI_get  
  12.       (JNIEnv * env, jobject obj)  
  13.     {  
  14.       return i;  
  15.     }  
 
4、
    生成:对象文件TestJNI.o (注意,运行下面命令可能会报错,主要是gcc没有安装或者安装的不是那个版本,所以重新装一次就好了,命令:yum install gcc gcc-c++ gcc-g77
        gcc -Wall -fPIC -c TestJNI.c -I./ -I/home/abc/jdk1.7/include -I/home/abc/jdk1.7/include/linux
        生成动态库libgoodlucky.so  注意这里的goodlucky 对应TestJNI.java中goodlucky。并且这里要以lib开头命名动态库.-Wall 显示错误和警告提示   -I(不是l,就是这个害死我了,汗)后面是 jni.h,jni_md.h的路径
        gcc -Wall -rdynamic -shared -o libgoodlucky.so TestJNI.o
    
      上面的两条命令等价于下面的命令:
        gcc -Wall -fPIC  -I./ -I/usr/java/jdk1.6.0_45/include -I/usr/java/jdk1.6.0_45/include/linux -shared -o libgoodlucky.so TestJNI.c
 
       另外一种:  (g++ Base64Coder.cpp  desMethod.cpp -fPIC -shared -o desAlgorithm.so )(目前还不可用)
        export CLASSPATH=$CLASSPATP:./jna.jar 
        g++ one.cpp two.cpp three.cpp -lstdc++ -fPIC -shared -o libtest.so
        export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${你的so目录}
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/you/libMyLibrary_jna.so
        编译器选项-fpic和链接器选项-shared
        
    注:编译C的语句:
    gcc -fpic -c test.c   (将C编译成o文件)
    gcc -shared -o libtest.so test.o (将o文件编译成so文件)
    
        修改.bash_profile文件,配置环境变量,由于生成的.so文件在当前目录下,故
 
        .bash_profile文件设置如下
        export LD_LIBRARY_PATH=./
        或者把生成的.so文件放到/usr/lib目录下也可以。
5、java TestJNI
//JNA导入jar包
export CLASSPATH=$CLASSPATP:./jna.jar 
 
 
进阶:
1、在第四步中,编写makefile文件
  内容如下:
 
[plain] view plaincopy
 
  1. libgoodlucky.so:TestJNI.o makefile  
  2.     gcc -Wall -rdynamic -shared -o libgoodlucky.so TestJNI.o  
  3. TestJNI.o:TestJNI.c TestJNI.h  
  4.     gcc -Wall -c TestJNI.c -I./ -I/home/abc/jdk1.7/include -I/home/abc/jdk1.7/include/linux  
  5. cl:  
  6.     rm -rf *.o *.so  



格式如下:
                一个 makefile 主要含有一系列的规则,如下:
                A: B
                (tab)<command>
                (tab)<command>
                
                每个命令行前都必须有tab符号。
具体可参考:http://goodcandle.cnblogs.com/archive/2006/03/30/278702.html
参考见:
http://watershitter.iteye.com/blog/477615#comments
http://lwjlaser.iteye.com/blog/779270
http://blog.csdn.net/kangkanglou/article/details/5807787

思考若是java文件带有包路径呢?可以去动手做做
posted @ 2015-11-18 15:05  流沙吹风  阅读(365)  评论(0编辑  收藏  举报