JNI 编译问题

最近在阅读有关jni的文档,想在Ubuntu下尝试一下文档中的简单例子,结果出现一些编译错误等一系列问题。这里将整个流程以及遇到的问题共享给大家。

1.配置java环境

其实我们只要从官网下载java JDK ,之后解压便成。例如这里我是从如下网址下载的 jdk1.7 :

http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html

 Linux x6491.85 MB   jdk-7u25-linux-x64.tar.gz

具体下载什么版本,要看您的系统是什么样的,我的是linux 64 位的,故下载该版本。

下载完后解压它,就算环境已经ok了。接下来我们开始以一个简单的例子进行编译。


2. 定义本地方法

编写如下代码,以HelloWorld.java 命名,该代码中包含一个本地方法“private native void print();"

class HelloWorld {
private native void print(); //本地方法
public static void main(String[] args) {
new HelloWorld().print(); //调用本地方法
}
static {
System.loadLibrary("HelloWorld"); //导入动态库
}
}

3.编译HelloWorld类

这里假设JDK 包同源码都放置在~/JNI 目录,解压后在该目录中将看到 一个“jdk1.7.0_25” 目录,这个就是我们的java 环境。这样我们执行如下命令,将生成HelloWorld.class文件。

~/JNI$ ./jdk1.7.0_25/bin/javac  HelloWorld.java


4.创建本地方法头文件HelloWorld.h

执行如下命令:

~/JNI$ ./jdk1.7.0_25/bin/javah -jni  HelloWorld

HelloWold.h 内容如下:

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

#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloWorld
 * Method:    print
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloWorld_print
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

5. 实现本地方法HelloWorld.c

具体内容如下:

#include <jni.h>
#include <stdio.h>
#include "HelloWorld.h"
JNIEXPORT void JNICALL
Java_HelloWorld_print(JNIEnv *env, jobject obj)
{
printf("Hello World!\n");
return;
}


6.编译本地方法生成so 库

执行如下命令生成so库:

~/JNI$ gcc -shared -I ./jdk1.7.0_25/include -I ./jdk1.7.0_25/include/linux -I /usr/include  HelloWorld.c -o libHelloWorld.so

执行以上命令之后出现如下的错误:

/usr/bin/ld: /tmp/cch0Ohfg.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
/tmp/cch0Ohfg.o: could not read symbols: Bad value
collect2: ld returned 1 exit status

我们加入-fPIC 选项重新编译:

~/JNI$ gcc -fpic -shared -I ./jdk1.7.0_25/include -I ./jdk1.7.0_25/include/linux -I /usr/include  HelloWorld.c -o libHelloWorld.so

编译成功。

执行ls 查看结果如下:

 HelloWorld.c  HelloWorld.class  HelloWorld.h  HelloWorld.java   jdk1.7.0_25 libHelloWorld.so


7.运行程序

~/JNI$ ./jdk1.7.0_25/bin/java  HelloWorld 


Exception in thread "main" java.lang.UnsatisfiedLinkError: no HelloWorld in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1878)
    at java.lang.Runtime.loadLibrary0(Runtime.java:849)
    at java.lang.System.loadLibrary(System.java:1087)
    at HelloWorld.<clinit>(HelloWorld.java:11)


出现找不到so库的错误。

这里我们将libHelloWorld.so 移到/usr/lib 目录.

~/JNI$ sudo mv libHelloWorld.so /usr/lib


之后再运行程序:

~/JNI$ ./jdk1.7.0_25/bin/java  HelloWorld

Hello World! //结果出来了


到此就算成功了。

8.总结

这里只是在Ubuntu 环境下,标准的jni编译过程,对于Android jni 编程来说,有另一套编译机制,在以后的文章中将会论及。





















  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值