【问题标题】:Loading a dynamic C shared library using JNI which also loads another shared library使用 JNI 加载动态 C 共享库,该库还加载另一个共享库
【发布时间】:2014-03-04 07:11:30
【问题描述】:

在 Java eclipse (Linux) 上使用 JNI,我正在加载一个名为 first.so 的动态共享库。 到目前为止一切顺利。 问题在于,first.so 还加载了一个名为 second.so 的动态库。

在运行程序时,我收到许多关于位于 second.so 中的符号的“未定义符号”错误。

似乎使用 JNI 加载的库无法在运行时加载其他 C 库,因为我们处于 Java 环境中。我的假设正确吗? 我是否需要特殊的编译标志来编译 first.so 库,或者是否需要特殊的参数来告诉 eclipse 它将在运行时尝试加载 .so?

提前致谢!

【问题讨论】:

  • second.so 是另一个 JNI 库还是只是一个仅由 first.so 使用的普通 C 库?如果它是一个 JNI 库,我认为您可能需要使用 System.loadLibrary() 从 Java 加载它,而不是使用 dlopen() 从 C 加载它,尽管我不确定。
  • second.so 是一个普通的 C 库,仅供 first.so 使用。
  • 在构建first.so时,在其中链接libsecond.so

标签: c linux eclipse java-native-interface shared-libraries


【解决方案1】:

似乎使用 JNI 加载的库无法在运行时加载其他 C 库,因为我们处于 Java 环境中。我的假设正确吗?

没有。

libfirst.so 如何使用libsecond.so?是链接依赖,还是dlopen加载的?

我发现了类似的东西:

static {
    System.loadLibrary("second");
    System.loadLibrary("first");
}

在使用 JNI 的类中通常可以工作。

编辑:现在我知道你是如何加载 libsecond.so 这对我有用:

Test.java

public class Test {

    public static void main (String args[]) {
        test();
    }

    private native static void test();

    static {
        System.loadLibrary("first");
    }
} 

first.c -- libfirst.so的唯一翻译单元

#include <jni.h>
#include "Test.h"
#include <dlfcn.h>
#define LIBNAME "libsecond.so"

#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Test
 * Method:    test
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_Test_test(JNIEnv *env , jclass cls)
{
  void* h;
  void (*sym)(void);

  h = dlopen(LIBNAME, RTLD_LAZY|RTLD_GLOBAL);
  if (h) {
    printf("dlopen " LIBNAME " worked\n");
    sym = (void (*)(void))dlsym(h,"second");
    sym();
  } else {
    printf("dlopen " LIBNAME " failed\n");
  }
}

#ifdef __cplusplus
}
#endif

second.c -- libsecond.so的唯一翻译单元

#include <stdio.h>

void
second(void)
{
  printf("hello from second\n");
}

生成文件

CFLAGS=-fPIC

all : libfirst.so libsecond.so 

libsecond.so : second.o
        $(CC) -shared -Wl,-soname,libsecond.so.0 -o $@ $^ -lc

libfirst.so : first.o
        $(CC) -shared -Wl,-soname,libfirst.so.0 -o $@ $^ -ldl -lc

clean:
        rm -f *.o *.so

Test.h 可以由javah Test 生成。请注意,libfirst.solibsecond.so 没有链接在一起。

【讨论】:

  • 感谢您的快速响应。 libsecond.so 由 dlopen 加载。
  • 似乎足以以正确的顺序加载库,如响应顶部所示 (System.loadLibrary("second"); System.loadLibrary("first");)
【解决方案2】:

所有常规规则都适用于从 Java 加载的库中的 dopen()。特别是,您检查您的LD_LIBRARY_PATHrpath, runpath 等。另请参阅dlopen failed:cannot open shared object file: No such file or directory

【讨论】:

    猜你喜欢
    • 2019-04-17
    • 1970-01-01
    • 2014-01-22
    • 1970-01-01
    • 1970-01-01
    • 2013-05-25
    • 2013-11-22
    • 2011-11-13
    相关资源
    最近更新 更多