在嵌入式 Linux 平台上将 libc 与 JNI 代码链接 (GuruPlug)

发布于 2024-12-13 06:04:53 字数 1775 浏览 3 评论 0原文

我正在尝试在嵌入式 Linux 平台(GuruPlug 计算机)上编译一个简单的 JNI 应用程序,但由于某种原因它没有正确链接到 libc。我正在编译的 Java 程序称为 Test.java:

public class Test {
    static {
        System.loadLibrary("Test");
    }

    public static void main(String[] args) {
        new Test().printMessage();
    }

    public native void printMessage();
}

printMessage() 的实现在 Test.c 中:

#include <jni.h>
#include <stdio.h>
#include "Test.h"

JNIEXPORT void JNICALL Java_Test_printMessage(JNIEnv *env, jobject obj)
{
    printf("Message 123...\n");
}

我正在 bash shell 上使用以下命令编译 Test.c:

gcc -g -shared -static -lc -Wl,-soname,libTest.so -I${JAVA_HOME}/include/ -I${JAVA_HOME}/include/linux/ Test.c -o libTest.so

当我运行上述命令时,我得到错误消息“共享对象中不允许 R_ARM_TLS_LE32 重定位”。完整的错误消息是:

/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabi/4.4.5/../../../libc.a(dl-tsd.o)(.text+0x18): R_ARM_TLS_LE32 relocation not permitted in shared object

尽管出现错误消息,JNI .so 文件仍然由编译器编写,但运行 Java 应用程序会出现以下错误消息:

Exception in thread "main" java.lang.UnsatisfiedLinkError: /usr/lib/jni/libTest.so: /usr/lib/jni/libTest.so: unexpected reloc type 0x03
        at java.lang.ClassLoader$NativeLibrary.load(Native Method)
        at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1750)
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1675)
        at java.lang.Runtime.loadLibrary0(Runtime.java:840)
        at java.lang.System.loadLibrary(System.java:1047)
        at Test.<clinit>(Test.java:3)
Could not find the main class: Test. Program will exit.

有人知道如何解决此问题吗?诚然,上面的代码是一个玩具示例,但我需要在这个平台上编译一个真正的JNI库,而真正的JNI库依赖于libc。我似乎无法解决将 libc 与 JNI 库链接的基本问题。任何建议将不胜感激。

谢谢!

I'm trying to compile a simple JNI application on an embedded Linux platform (a GuruPlug computer), but for some reason it's not linking to libc properly. The Java program I'm compiling is called Test.java:

public class Test {
    static {
        System.loadLibrary("Test");
    }

    public static void main(String[] args) {
        new Test().printMessage();
    }

    public native void printMessage();
}

The implementation of printMessage() is in Test.c:

#include <jni.h>
#include <stdio.h>
#include "Test.h"

JNIEXPORT void JNICALL Java_Test_printMessage(JNIEnv *env, jobject obj)
{
    printf("Message 123...\n");
}

I'm compiling Test.c with the following command on a bash shell:

gcc -g -shared -static -lc -Wl,-soname,libTest.so -I${JAVA_HOME}/include/ -I${JAVA_HOME}/include/linux/ Test.c -o libTest.so

When I run the above command, I get the error message "R_ARM_TLS_LE32 relocation not permitted in shared object". The full error message is:

/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabi/4.4.5/../../../libc.a(dl-tsd.o)(.text+0x18): R_ARM_TLS_LE32 relocation not permitted in shared object

Despite the error message, the JNI .so file is still written by the compiler, but running the Java application gives the following error message:

Exception in thread "main" java.lang.UnsatisfiedLinkError: /usr/lib/jni/libTest.so: /usr/lib/jni/libTest.so: unexpected reloc type 0x03
        at java.lang.ClassLoader$NativeLibrary.load(Native Method)
        at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1750)
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1675)
        at java.lang.Runtime.loadLibrary0(Runtime.java:840)
        at java.lang.System.loadLibrary(System.java:1047)
        at Test.<clinit>(Test.java:3)
Could not find the main class: Test. Program will exit.

Does anybody have any idea how to go about fixing this? Admittedly, the above code is a toy example, but I need to get a real JNI library compiling on this platform, and the real JNI library depends on libc. I can't seem to solve this basic issue of linking libc with a JNI library. Any suggestions would be greatly appreciated.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

绳情 2024-12-20 06:04:53

gcc -g -shared -static -lc -Wl,-soname,libTest.so -I${JAVA_HOME}/include/ -I${JAVA_HOME}/include/linux/ Test.c -o libTest .so

上面的命令行有几个问题:

  • -shared-static 标志是互斥的,
  • 当链接共享库时,第二个会覆盖第一个,你想-fPIC 在大多数体系结构上,
  • -lc 位于错误的位置(应该在您的源代码之后,而不是在它们之前),并且无论如何都没有必要:gcc 会自动添加
  • 它也并不严格需要 -soname ;这只是无用的混乱

正确的命令是:

gcc -g -shared -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux \
  Test.c -o libTest.so

gcc -g -shared -static -lc -Wl,-soname,libTest.so -I${JAVA_HOME}/include/ -I${JAVA_HOME}/include/linux/ Test.c -o libTest.so

There are several problems with the command line above:

  • the -shared and -static flags are mutually exclusive, and the second overrides the first
  • when linking shared libraries, you want -fPIC on most architectures
  • the -lc is in the wrong place (should follow your sources, not precede them), and is not necessary anyway: gcc will add it automatically
  • you don't strictly need the -soname either; it's just useless clutter

The correct command then is:

gcc -g -shared -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux \
  Test.c -o libTest.so
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文