不满意的链接错误:java.library.path中没有库文件
我有这样的目录结构
. --compile_c.sh --compile_java.sh --config.sh --execute_java.sh --run.sh --src --ccode --jnitest_SimpleJNITest.h --rtm_simple.c --jnitest --SimpleJNITest.java --lib --rtm_simple.so --classes --SimpleJNITest.class
当它具有在rtm_simple.c
充实的native
方法时,如何正确运行rtm_simple.c
?
目前,我已定义
config.sh
targetDir="classes" libDir="lib" srcDir="src" MainPackage="jnitest" Main="SimpleJNITest" ccodeDir="ccode" cFileName="rtm_simple" jdkDir="/home/user/local/java/jdk1.7.0_65" mkdir -p "$targetDir" mkdir -p "$libDir"
我正试图跑
run.sh
#!/bin/bash source compile_java.sh javah -d "${srcDir}/${ccodeDir}" -cp "$targetDir" -jni "${MainPackage}.${Main}" source compile_c.sh source execute_java.sh
哪里
compile_java.sh
#!/bin/bash source config.sh javac -d "$targetDir" -sourcepath "$srcDir" -cp "${targetDir}:${libDir}/*" "${srcDir}/${MainPackage}/${Main}.java"
compile_c.sh
#!/bin/bash source config.sh cFile="${srcDir}/${ccodeDir}/${cFileName}.c" soFile="${libDir}/${cFileName}.so" gcc -g -shared -fpic -I "${jdkDir}/include" -I "${jdkDir}/include/linux" $cFile -o $soFile
execute_java.sh
#!/bin/bash source config.sh export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${libDir}" java -cp "${targetDir}:${libDir}/*" "${MainPackage}.${Main}"
(也试过java -Djava.library.path="$LD_LIBRARY_PATH:$libDir" -cp "${targetDir}:${libDir}/*" "${MainPackage}.${Main}"
)
产量
$ ./run.sh Exception in thread "main" java.lang.UnsatisfiedLinkError: no rtm_simple in java.library.path at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867) at java.lang.Runtime.loadLibrary0(Runtime.java:870) at java.lang.System.loadLibrary(System.java:1122) at jnitest.SimpleJNITest.main(SimpleJNITest.java:17)
码:
SimpleJNITest.java
package jnitest; public class SimpleJNITest{ public static final int NOF_ITERATIONS = 100000; public native int nofAborts(int nofTransactions); public void test(){ int nofAborts = nofAborts(NOF_ITERATIONS); System.out.println(String.format("successfully completed %d transactions and had to retry %d times",nofAborts)); } public static void main(String[] args) { System.loadLibrary("rtm_simple"); new SimpleJNITest().test(); } }
(也尝试使用System.loadLibary("rtm_simple.so");
)
jnitest_SimpleJNITest.h
/* DO NOT EDIT THIS FILE - it is machine generated */ #include /* Header for class jnitest_SimpleJNITest */ #ifndef _Included_jnitest_SimpleJNITest #define _Included_jnitest_SimpleJNITest #ifdef __cplusplus extern "C" { #endif #undef jnitest_SimpleJNITest_NOF_ITERATIONS #define jnitest_SimpleJNITest_NOF_ITERATIONS 100000L /* * Class: jnitest_SimpleJNITest * Method: nofAborts * Signature: (I)I */ JNIEXPORT jint JNICALL Java_jnitest_SimpleJNITest_nofAborts (JNIEnv *, jobject, jint); #ifdef __cplusplus } #endif #endif
rtm_simple.c
#include #include "jnitest_SimpleJNITest.h" JNIEXPORT jint JNICALL Java_jnitest_SimpleJNITest_nofAborts(JNIEnv* env, jobject obj, jint nof_iterations){ volatile int abort_counter = 0; volatile int i = 0; while (i jump to local label 2*/ "1:\n\t" /*local label 1 (jumped to when transaction is aborted)*/ :"+rm"(abort_counter) /*artificial dependency*/ :"rm"(i) /*artificial dependency*/ ); ++abort_counter; __asm__ __volatile__ ( "2:" /*local label 2 (jumped to when transactoin is NOt aborted)*/ :"+rm"(abort_counter) /*artificial dependency*/ :"rm"(i) /*artificial dependency*/ ); } if(i != nof_iterations) return -1; return abort_counter; }
如果要指定文件名,则需要使用System.load(String)
,而不是System.loadLibrary(String)
方法。 loadLibrary
以与平台相关的方式转换指定的名称。 在您的系统上,可能会添加一个lib
前缀和.so
后缀,但这意味着无论您如何调用loadLibrary
,它都无法加载名为rtm_simple.so
的文件,即使它位于库搜索路径上也是如此。 或者换句话说,如果您确实想使用loadLibrary
,则需要将文件重命名为librtm_simple.so
。
如果在strace -fF
下运行它,您可以看到JVM使用的路径。
建议您将System.loadLibrary()放在SimpleJNITest类的静态块中。 您可能需要在main中创建SimpleJNITest对象时更明确。
public class SimpleJNITest{ public static final int NOF_ITERATIONS = 100000; static { System.loadLibrary("rtm_simple"); } public static void main(String[] args) { SimpleJNITest simple = new SimpleJNITest(); simple.text(); } }