不满意的链接错误:java.library.path中没有库文件 [英] Unsatisfied link error: no library file in java.library.path

查看:144
本文介绍了不满意的链接错误: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

SimpleJNITest具有在rtm_simple.c中充实的native方法时,如何正确运行SimpleJNITest?

How do I correctly run SimpleJNITest when it has a native method that is fleshed out in 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 <jni.h>
/* 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 <jni.h>
#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 < nof_iterations) {
        __asm__ __volatile__ (
            "xbegin 1f" /*1f: local label 1, look forward to find first*/
                :"+rm"(i) /*artificial dependency to prevent re-ordering*/
        ); 

        ++i;

        __asm__ __volatile__ (
            "xend\n\t"
            "jmp 2f\n" /*not aborted ==> 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;
}

推荐答案

如果要指定文件名,则需要使用

If you want to specify a file name, you need to use System.load(String), and not the System.loadLibrary(String) method. loadLibrary transforms the specified name in a platform-dependent manner. On your system, a lib prefix and .so suffix is probably added, but this means no matter how you call loadLibrary, it won't be able to load a file called rtm_simple.so even if it is located on the library search path. Or put differently, if you do want to use loadLibrary, you need to rename the file to librtm_simple.so.

如果在strace -fF下运行JVM,则可以看到JVM使用的路径.

You can see the paths the JVM uses if you run it under strace -fF.

这篇关于不满意的链接错误:java.library.path中没有库文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆