使用JNI加载动态C共享库,该库还可以加载另一个共享库

6
在Java Eclipse(Linux)上使用JNI,我正在加载一个名为first.so的动态共享库。到目前为止一切顺利。 问题是first.so还加载了一个名为second.so的动态库,运行程序时我会得到许多有关second.so中符号未定义的错误信息。 似乎在Java环境下使用JNI加载的库无法在运行时加载其他C库。我的假设是否正确? 我需要特殊的编译标志来编译first.so库吗?还是需要特殊参数告诉eclipse在运行时将尝试加载一个.so? 提前感谢!

second.so是另一个JNI库还是仅由first.so使用的普通C库?如果它是一个JNI库,我认为您可能需要使用System.loadLibrary()从Java中加载它,而不是使用dlopen()从C中加载,尽管我不确定。 - Adam Rosenfield
second.so是一个普通的C库,只被first.so使用。 - Ori Gil
在构建 first.so 时,将 libsecond.so 链接到其中。 - Basile Starynkevitch
2个回答

2

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

不是。

libsecond.so 是由 libfirst.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.clibsecond.so唯一的翻译单元。

#include <stdio.h>

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

Makefile

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加载的。 - Ori Gil
似乎只需按照响应顶部所示的顺序加载库即可(System.loadLibrary("second"); System.loadLibrary("first");)。 - pevik

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接