我用的是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已经是最简单的了,但是还是运行不了,请问是不是我哪里漏了呢?请高手指教!

解决方案 »

  1.   

    是不是放错地方了,这好像不是不java的
      

  2.   

    你把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);
          }
      }
      

  3.   

    没做过linux下的jni,不过个人感觉是
     System.load("/home/user/Linux/libkk.so");出了问题,运行程序的用户可能与你的用户并不一致,导致/home/user目录不一致一般我都是把so/dll放在java.library.path环境下,然后System.loadLibrary("libkk"),
      

  4.   

    我也改用环境变量了,但是还是不行,应该不太可能是这句出错把,如果是这句有问题,就应该在load的时候就报错的,但是我是在调用这个函数的时候才报错哦~~~晕啊~~~
      

  5.   

    首先看一下libkk.so是否具有可执行权限
    然后把libkk.so拷贝到/lib/目录下
    最后修改Java类代码static{
        // 加载 libkk.so
        // 注意加载名需要去掉lib前缀及.so后缀
        System.loadLibrary("kk");
    }试一下吧,在我这里测试通过了。
      

  6.   

    检查你的c源程序中函数的定义是否正确,特别是Java_sotest2_get函数,在我的测试中,将Java_sotest2_get改名为Java_sotest2_gett后进行编译,
    运行时会出现你所描述的错误。
      

  7.   

    就是说,错误原因是libkk.so文件中没有Java_sotest2_get这个函数。
    查一下吧!
      

  8.   

    谢谢!但是我查过了,是有的,我的头文件是通过我的class文件生成的,而且头文件的方法我是直接复制粘贴到cpp文件中的,所以应该不会存在写错的问题吧~~我老实提示这个出错~~~郁闷啊~~~
      

  9.   

    我的测试过程,请参考。
    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.ogcc -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.classjava Test看到的内容是10
      

  10.   

    终于找到问题啦!原来是我的生成so的命令有问题啊,生成出来的so中的函数多了一个下划线,晕~~~非常感谢darxin的回复!谢谢各位!