求救~~java调用so里的函数

ichiko 2009-11-30 02:53:44
我用的是ubuntu 9.04,现在有一个so文件,是我自己写的(符合JNI调用的标准),但是我在java调用时确提示“Exception in thread "main" java.lang.UnsatisfiedLinkError: sotest2.get()I”,我的代码如下,请高手指教!
java代码如下:

public class sotest2 {

static{
System.load("/home/user/Linux/libkk.so");
}
public native static int get();
public native static int set(int i,int j);
public static void main(String args[]){
sotest2 test = new sotest2();
int i = -1;
//int i=test.set(0,38400);
i=test.get();
System.out.println("result = "+i);
}

}


用编译生成class文件,再用javah命令生成.h文件
在c++编译器中新建一个项目
其头文件如下:

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

#ifndef _Included_sotest2
#define _Included_sotest2
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: sotest2
* Method: get
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_sotest2_get
(JNIEnv *, jclass);

/*
* Class: sotest2
* Method: set
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_sotest2_set
(JNIEnv *, jclass, jint, jint);

#ifdef __cplusplus
}
#endif
#endif


cpp文件如下:

#include<dlfcn.h>
#include<stdio.h>
#include<stdlib.h>
#include"sotest3.h"

JNIEXPORT jint JNICALL Java_sotest2_get
(JNIEnv * env, jclass obj)
{
return 10;
}
JNIEXPORT jint JNICALL Java_sotest2_set
(JNIEnv * env, jclass obj, jint a, jint b){
return 12;
}


之后生成了一个so文件libkk.so
并把该文件放在"/home/user/Linux"下
最后运行上边的java代码,但是就提示:
Exception in thread "main" java.lang.UnsatisfiedLinkError: sotest2.get()I
at sotest2.get(Native Method)
at sotest2.main(sotest2.java:28)
Java Result: 1


真不知道是什么原因,我做的这个so已经是最简单的了,但是还是运行不了,请问是不是我哪里漏了呢?请高手指教!
...全文
579 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
ichiko 2009-12-03
  • 打赏
  • 举报
回复
终于找到问题啦!原来是我的生成so的命令有问题啊,生成出来的so中的函数多了一个下划线,晕~~~非常感谢darxin的回复!谢谢各位!
ichiko 2009-12-01
  • 打赏
  • 举报
回复
谢谢!但是我查过了,是有的,我的头文件是通过我的class文件生成的,而且头文件的方法我是直接复制粘贴到cpp文件中的,所以应该不会存在写错的问题吧~~我老实提示这个出错~~~郁闷啊~~~
darxin 2009-12-01
  • 打赏
  • 举报
回复
我的测试过程,请参考。
Java代码(Test.java):

class Test {
static {
System.load("/lib/libtestjni.so");
}

public static native int get();

public static void main(String[] args) {
Test t = new Test();
System.out.println(t.get());
}
}


调用javah生成的C头文件(Test.h)

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

#ifndef _Included_Test
#define _Included_Test
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Test
* Method: get
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_Test_get
(JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif


自定义的C源程序(Test.c)

#include<dlfcn.h>
#include<stdio.h>
#include<stdlib.h>

#include "Test.h"

JNIEXPORT jint JNICALL Java_Test_get
(JNIEnv* env, jobject obj) {

return 10;
}


我使用的是OpenJDK 6.0,使用以下命令编译Test.c,生成Test.o

gcc -Wall -c -o Test.o Test.c -I/usr/lib/jvm/java-6-openjdk/include -I/usr/lib/jvm/java-6-openjdk/include/linux

查看Test.o的内容,使用以下命令

nm Test.o

看到的内容如下:

00000000 T Java_Test_get

用以下命令生成so文件

gcc -Wall -rdynamic -shared -o libtestjni.so Test.o

查看libtestjni.so的内容,使用以下命令

nm libtestjni.so

看到的内容如下:

000003ec T Java_Test_get
00001f20 a _DYNAMIC
00001ff4 a _GLOBAL_OFFSET_TABLE_
w _Jv_RegisterClasses
00001f10 d __CTOR_END__
00001f0c d __CTOR_LIST__
00001f18 d __DTOR_END__
00001f14 d __DTOR_LIST__
00000454 r __FRAME_END__
00001f1c d __JCR_END__
00001f1c d __JCR_LIST__
0000200c A __bss_start
w __cxa_finalize@@GLIBC_2.1.3
00000400 t __do_global_ctors_aux
00000330 t __do_global_dtors_aux
00002008 d __dso_handle
w __gmon_start__
000003e7 t __i686.get_pc_thunk.bx
0000200c A _edata
00002014 A _end
00000438 T _fini
000002cc T _init
0000200c b completed.6625
00002010 b dtor_idx.6627
000003b0 t frame_dummy

将libtestjni.so拷贝到/lib/

sudo cp libtestjni.so /lib

调用Test.class

java Test

看到的内容是

10
darxin 2009-11-30
  • 打赏
  • 举报
回复
就是说,错误原因是libkk.so文件中没有Java_sotest2_get这个函数。
查一下吧!
darxin 2009-11-30
  • 打赏
  • 举报
回复
检查你的c源程序中函数的定义是否正确,特别是Java_sotest2_get函数,

在我的测试中,将Java_sotest2_get改名为Java_sotest2_gett后进行编译,
运行时会出现你所描述的错误。
darxin 2009-11-30
  • 打赏
  • 举报
回复
首先看一下libkk.so是否具有可执行权限
然后把libkk.so拷贝到/lib/目录下
最后修改Java类代码

static{
// 加载 libkk.so
// 注意加载名需要去掉lib前缀及.so后缀
System.loadLibrary("kk");
}

试一下吧,在我这里测试通过了。
ichiko 2009-11-30
  • 打赏
  • 举报
回复
我也改用环境变量了,但是还是不行,应该不太可能是这句出错把,如果是这句有问题,就应该在load的时候就报错的,但是我是在调用这个函数的时候才报错哦~~~晕啊~~~
shine333 2009-11-30
  • 打赏
  • 举报
回复
没做过linux下的jni,不过个人感觉是
System.load("/home/user/Linux/libkk.so");出了问题,运行程序的用户可能与你的用户并不一致,导致/home/user目录不一致

一般我都是把so/dll放在java.library.path环境下,然后System.loadLibrary("libkk"),
ichiko 2009-11-30
  • 打赏
  • 举报
回复
知道的高手请教我一下啊,万分感激啊~~~
ichiko 2009-11-30
  • 打赏
  • 举报
回复
怎么每人呢~~~~~
ichiko 2009-11-30
  • 打赏
  • 举报
回复
去掉了,到那时还是不行~~~~还是提示这个错~~
darxin 2009-11-30
  • 打赏
  • 举报
回复
你把get/set的static修饰符去掉,然后重新生成C++的头文件和类文件。

public class sotest2 {

static{
System.load("/home/user/Linux/libkk.so");
}

public native int get();
public native int set(int i,int j);

public static void main(String args[]){
sotest2 test = new sotest2();
int i = -1;
//int i=test.set(0,38400);
i=test.get();
System.out.println("result = "+i);
}
}
jx362531 2009-11-30
  • 打赏
  • 举报
回复
是不是放错地方了,这好像不是不java的

67,515

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧