jni笔记1

来源:互联网 发布:东方网络最新公告 编辑:程序博客网 时间:2024/06/03 20:15

最近看openjdk,想记录点东西,openjdk很多都是jni接口,于是自己仿照着些点例子玩玩。等熟悉 的差不多之后继续做笔记,研究openjdk。今天从最简单的开始,hello world,不带参数的jni调用。我是在linux下编写的。


第一步,建立hello.h以及hello.c
#ifndef __HELLO_H__  //防止重复导入头文件内容
#define __HELLO_H__  //


#include <jni.h>  //包含jni头文件
//如果定义了c++常量,则指定采用c的编译方式(extern "C")
#ifdef __cplusplus 
extern "C"{
#endif


/**JNIEXPORT关键字 + void返回类型 + JNICALL关键字 + 方法名称(前缀Java_ + JAVA类名Hello + 加下划线_ + 本地方法名称) + 方法参数(JNIEnv是jni的环境通过这个指针你才能将java语言使用的对象或者参数传给c语言使用,jobject是this)

*/

JNIEXPORT void JNICALL Java_Hello_hello(JNIEnv *, jobject);


#ifdef __cplusplus
}
#endif


#endif


//定义函数
#include<jni.h>
#include"hello.h"
#include<stdio.h>


JNIEXPORT void JNICALL
Java_Hello_hello(JNIEnv *env, jobject obj)
{
        printf("Hello world jni !\n");


        return;
}


第二步,编译成so
gcc -shared -I$JAVA_HOME/include  hello.c -o libhello.so(-I可以指定额外包含的头文件位置)
问题1 : 执行上面语句居然报错了,/usr/tools/jdk1.7.0_60/include/jni.h:45:20: error: jni_md.h: No such file or directory
In file included from hello.c:1:,没有找到jni_md.h这个头文件。
我到jni.h中看到是包含了jni_md.h,find / -name "jni_md.h"发现在/usr/tools/jdk1.7.0_60/include/linux/jni_md.h,而jni.h的包含路径写错了,我改为了linux/jni_md.h。
问题2 :重新编译发现/usr/bin/ld: /tmp/cct09ZN0.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC,只读数据段冲突了,需要使用-fPIC重新编译,-fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时在内存的位置不是固定的
gcc -shared -I$JAVA_HOME/include  hello.c -o libhello.so重新编译,终于生成了so


第三步,编写java文件
class Hello{
//申明jni接口
        public native void hello();


        static{
/**
我这里想看看java去哪里找so位置,然后想加入当前目录,结果发现没有,还是报错。
*/
                String libPath = System.getProperty("java.library.path");
                System.out.println(libPath);
    
                libPath += ":.";    
    
                System.setProperty("java.library.path",libPath);
                System.out.println(System.getProperty("java.library.path"));
  //加载so
                System.loadLibrary("hello");
        }   


        public static void main(String[] args){
                System.out.println(System.getProperty("java.library.path"));
                new Hello().hello();
        }   
}
编译javac Hello.java ,运行java -cp . Hello
问题1 : 运行java -cp . Hello报错/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib:.
Exception in thread "main" java.lang.UnsatisfiedLinkError: no hello in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1886)
at java.lang.Runtime.loadLibrary0(Runtime.java:849)
at java.lang.System.loadLibrary(System.java:1088)
找不到so,解决办法1拷贝so到/usr/java/packages/lib/amd64 , /usr/lib64, /lib64, /lib,/usr/lib中的任何一个目录都可以;2 java -Djava.library.path=/home/leo/jni/test Hello指定java运行时-D是指定环境变量java.library.path的值。
最后运行结果/home/leo/jni/test
/home/leo/jni/test:.
/home/leo/jni/test:.

Hello world jni !


本以为挺简单的东西,如果不写的话,永远觉得简单,写出来之后,发现有如此多的问题,纸上谈兵还是不行,一定要动手

0 0
原创粉丝点击