java 我的JNI应用程序无法解析共享应用程序的依赖项

wi3ka0sx  于 2023-05-21  发布在  Java
关注(0)|答案(1)|浏览(143)

我想通过JNI从我的Java应用程序中使用第三方共享库。
(我在Manjaro Linux上运行,目前使用命令行工具)
如果我不在www.example.com中创建第三方库的依赖项,我可以很好地构建和运行它myLib.so。
一旦我创建了一个从myLib.so到第三方库的依赖项,Java调用就会失败

java: symbol lookup error: myLib.so: undefined symbol: acOpenSystem

我已经尝试将库路径设置为库的位置,但仍然失败。

java -Djava.library.path=.:$ARENA_LIBS:$ARENALIBS2 MyClass

我确信有一些简单的东西我错过了,但我似乎不能从网络上占卜出答案。请帮帮我即使是一个链接到一个盲目明显的资源,我没有找到将是受欢迎的;- )
谢谢
编辑:这里是来源。HelloWorld -> Foo -> Bar Bar. c

#include <stdio.h>
 
void bar(void)
{
    puts("\nHello, I am a shared library called BAR");
}

bar.h

#ifndef bar_h__
#define bar_h__
 
extern void bar(void);
 
#endif  // bar_h_

食品c:

#include <jni.h>
#include <stdio.h>
#include "bar.h"
#include "HelloWorld.h"
 
// https://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html
 
void foo(void)
{
    puts("\nHello, I am a shared library");
    bar();
}

JNIEXPORT void JNICALL Java_HelloWorld_foo
  (JNIEnv *, jobject) {
    foo();
 }

foo.h:

#ifndef foo_h__
#define foo_h__
 
extern void foo(void);
 
#endif  // foo_h_

HelloWorld.h:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */

#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloWorld
 * Method:    foo
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloWorld_foo
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

HelloWorld.java:

import java.io.File;

class HelloWorld {

    public static void main(String[] args) {
        try {
            File file = new File("libFoo.so");
            String path = file.getAbsoluteFile().toPath().toString();
            System.out.println("path = "+ path);
            System.load(path);
            System.out.println("Hello from java app"); // Display the string.
            new HelloWorld().foo();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    private native void foo();
}

我的脚本文件:

#!/bin/sh

SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )

# https://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html
# compile foo
gcc -c -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" -Wall -Werror -fpic foo.c
# link object into shared library
gcc -shared -o libFoo.so foo.o

# compile bar
gcc -c -Wall -Werror -fpic bar.c
# link object into shared library
gcc -shared -o libBar.so bar.o

LD_LIBRARY_PATH=::$LD_LIBRARY_PATH
export LD_LIBRARY_PATH
gcc -L$SCRIPT_DIR -o test hello-world.c -lFoo -lBar

./test

LD_LIBRARY_PATH=$SCRIPT_DIR:$LD_LIBRARY_PATH
echo "LD_LIBRARY_PATH: $LD_LIBRARY_PATH"
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH

javac HelloWorld.java
javac -h . HelloWorld.java
java -Djava.library.path=. HelloWorld

为了完整起见,c可执行文件的源代码可以证明问题不在c代码中:

#include <stdio.h>      // C Standard IO Header
#include "foo.h"

int main(int argc, char *argv[]) {
    printf("Hello from executable");
    foo();
}

c中的可执行文件运行正常,但java应用程序给出一个错误:

Hello from java app

Hello, I am a shared library
java: symbol lookup error: /mnt/data/singer/c/experiment/libFoo.so: undefined symbol: bar
java -version
openjdk version "17.0.5" 2022-10-18
OpenJDK Runtime Environment Temurin-17.0.5+8 (build 17.0.5+8)
OpenJDK 64-Bit Server VM Temurin-17.0.5+8 (build 17.0.5+8, mixed mode, sharing)

gcc --version
gcc (GCC) 12.2.1 20230201

在Manjaro 22.1上运行

vmdwslir

vmdwslir1#

我想我现在已经让它工作了。我会把我的剧本留给后人:

#!/bin/sh

#  Example of building JNI app.  
# Designed to run on linux using GCC and a suitable java compiler
#
# Uses an app 'HelloWorld' which invokes a shared library 'foo'.
# Foo depends upon 'bar' which is bound to foo either as
# - an object (bar.o)
# - a static library (bar.a)
# - a dynamic library (libBar.so)
#
# The java app is run once with each of the three forms of the shared library (libFoo.so) 

# compile java and create jni header file
javac HelloWorld.java
javac -h . HelloWorld.java

# compile bar
gcc -c -Wall -Werror -fpic bar.c

# link object into shared library
gcc -shared -o libBar.so bar.o

# link object into static library
ar rcs bar.a bar.o

# compile foo
gcc -c -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" -Wall -Werror -fpic foo.c

# Set up the LD_LIBRARY_PATH to resolve dynamic libraries at run time
# current working directory as a variable
cwd=$(pwd)
LD_LIBRARY_PATH=$cwd:$LD_LIBRARY_PATH
# echo "LD_LIBRARY_PATH: $LD_LIBRARY_PATH"
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH

echo
echo
echo
echo "************** Using Bar as object *************"
# link object into shared library an object library for Bar
gcc -shared -o libFoo.so foo.o bar.o
java -Djava.library.path=. HelloWorld

echo
echo
echo
echo "************** Using Bar as static library *************"
# link object into shared library a static library for Bar
gcc -shared -o libFoo.so foo.o -L . bar.a
java -Djava.library.path=. HelloWorld

echo
echo
echo
echo "************** Using Bar as dynamic library *************"
# link object into shared library using a dynamic library for Bar
gcc -shared -o libFoo.so foo.o -L . -lBar
java -Djava.library.path=. HelloWorld

相关问题