【问题标题】:linking libc with JNI code on embedded Linux platform (GuruPlug)在嵌入式 Linux 平台 (GuruPlug) 上将 libc 与 JNI 代码链接
【发布时间】:2011-10-31 19:30:55
【问题描述】:

我正在尝试在嵌入式 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 relocation not allowed in shared object”。完整的错误信息是:

/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 库链接的基本问题。任何建议将不胜感激。

谢谢!

【问题讨论】:

    标签: linux linker java-native-interface libc


    【解决方案1】:

    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
    

    【讨论】:

    • 谢谢!这真的很有帮助。我想出了一个非常长而且丑陋的命令来做到这一点,但是你写的看起来好多了。 (我打算在 8 小时窗口结束后立即回答我自己的问题;在那之前我没有足够的声誉来回答我自己的问题。)我之前提出的命令是这样的:gcc -g -shared -static -Wl,-soname,libTest.so -Wl,-Bstatic -lc -Wl,-Bdynamic -I${JAVA_HOME}/include/ -I${JAVA_HOME}/include/linux/ Test.c -o libTest.so 它有效,但肯定是太冗长了。
    猜你喜欢
    • 2017-05-21
    • 1970-01-01
    • 2015-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    相关资源
    最近更新 更多