【问题标题】:Java System.loadLibrary call on Linux freezesLinux 上的 Java System.loadLibrary 调用冻结
【发布时间】:2011-05-26 13:07:50
【问题描述】:

我有一个非常小的 .so 文件(可在此处获得:https://docs.google.com/leaf?id=0B4MxFm-ACB3INjhkMjhlNzktYzkxYy00Zjk5LTk0Y2MtZDE2MWQ2MzY1OWUy&hl=en_US&authkey=CMrJguwN

我正在尝试将其加载到 RHEL 上的 Java 中,而 Java main 只是冻结(没有错误或异常)。我在 LD_LIBRARY_PATH 上有包含 .so 文件的目录,所以我知道它实际上是在尝试加载它。

有什么办法可以解决这个问题吗?

public class SmallTester {


    public static void main(String[] args){

        for(String s: System.getenv("LD_LIBRARY_PATH").split(":")){
            System.out.println(s);
        }

        System.loadLibrary("TestAda");

        System.out.println("Here");
    }
}

编辑:

根据下面的帖子,我做了一个 strace.. 看起来它一遍又一遍地重复这个调用(虽然我不确定这意味着什么?):

[pid 31464] clock_gettime(CLOCK_MONOTONIC, {3605675, 624255544}) = 0
[pid 31464] gettimeofday({1306417113, 168967}, NULL) = 0
[pid 31464] clock_gettime(CLOCK_MONOTONIC, {3605675, 624435576}) = 0
[pid 31464] clock_gettime(CLOCK_MONOTONIC, {3605675, 624518205}) = 0
[pid 31464] gettimeofday({1306417113, 169216}, NULL) = 0
[pid 31464] clock_gettime(CLOCK_REALTIME, {1306417113, 169306590}) = 0
[pid 31464] futex(0x88b3f04, FUTEX_WAIT_PRIVATE, 1, {0, 49909410}) = -1 ETIMEDOUT (Connection timed out)

这里是完整版日志:https://docs.google.com/leaf?id=0B4MxFm-ACB3IYzdhZWIwNWEtYjUzMS00NGM5LWEzZjQtYzMzOWE3MWNhYWQ0&hl=en_US&authkey=CJ-Lv_wG

EDIT2:我也尝试使用 JNA 加载库:

public class SmallTesterJNA {

    public interface CLibrary extends Library {

      CLibrary INSTANCE1 = (CLibrary)
      Native.loadLibrary("TestAda", //  <<< our library goes here
                         CLibrary.class);

    }

    public static void main(String[] args){

        for(String s: System.getenv("LD_LIBRARY_PATH").split(":")){
            System.out.println(s);
        }

        System.loadLibrary(CLibrary.INSTANCE1.toString());

        System.out.println("Here");
    }
}

这是输出.. 看起来非常相似:https://docs.google.com/leaf?id=0B4MxFm-ACB3IYzdhZWIwNWEtYjUzMS00NGM5LWEzZjQtYzMzOWE3MWNhYWQ0&hl=en_US&authkey=CJ-Lv_wG

编辑2:

这是我附加到进程的 gcore 输出。不知道这告诉我什么:

(no debugging symbols found)
(no debugging symbols found)
[Thread debugging using libthread_db enabled]
[New Thread 0xb7fb26c0 (LWP 8326)]
[New Thread 0x7fa8eb90 (LWP 8340)]
[New Thread 0x7fe2db90 (LWP 8339)]
[New Thread 0x7fe7eb90 (LWP 8338)]
[New Thread 0x7feffb90 (LWP 8337)]
[New Thread 0x800afb90 (LWP 8336)]
[New Thread 0x80100b90 (LWP 8335)]
[New Thread 0x80351b90 (LWP 8334)]
[New Thread 0x803a2b90 (LWP 8333)]
[New Thread 0x80423b90 (LWP 8332)]
[New Thread 0x8066db90 (LWP 8331)]
[New Thread 0x806eeb90 (LWP 8330)]
[New Thread 0x8076fb90 (LWP 8329)]
[New Thread 0x807f0b90 (LWP 8328)]
[New Thread 0xb7474b90 (LWP 8327)]
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
0xb7fcd402 in __kernel_vsyscall ()
Saved corefile core.8326

【问题讨论】:

    标签: java linux shared-libraries


    【解决方案1】:

    如果我不得不猜测,我会说可能的罪魁祸首是共享对象的初始化代码。

    获取 JVM 进程的核心转储(使用 gcore)或附加 gdb 以获取确切冻结位置的堆栈跟踪。

    【讨论】:

      【解决方案2】:

      我通常在 gdb 之前尝试 strace(跟踪所有系统调用)。执行:

      strace -f java SmallTester > logfile 2>&1
      

      你会在logfile中得到很多信息,最后一部分是最有趣的。您会发现 jvm 进程正在寻找您的 TestAda.so 文件并查看它是否成功加载了 .so 文件。如果这不起作用,请恢复到 gdb。

      【讨论】:

      • 你能看一下上面的日志文件吗?知道发生了什么吗?
      • 我不认为 [pid 31464] 是问题所在,它只是一个 java 线程在等待某些东西。据我所见,jvm 在 /adapts/ad/irad-c2/builds/mark/workspace/ASOC_M/mukul-branch/Omnyx/Projects/Test/buildLinux-i686/lib/libTestAda.so 中找到了您的库,这导致加载 libgnarl-6.2.so、libgnat-6.2.so 和 libgcc_s.so.1。在一些初始化之后,线程/进程停止了(例如,没有执行系统调用),所以它要么在初始化代码中无限旋转(CPU 到 100%?),要么在某个锁上阻塞。
      【解决方案3】:

      查看 C++ 代码中的 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) 函数。它可能有一个无限循环 :) 如果尚未定义,也可以尝试定义它。

      有关JNI_OnLoad 的详细信息,请参阅here

      【讨论】:

      • 这实际上是一个 Ada 库.. 仍在尝试根据我在做什么来消化这篇文章
      • 如果您使用 JNI,您不能只加载 Ada 库并期望直接使用它。您需要将它与 JNI 接口,这意味着创建充当 Java 和 C++ 之间桥梁的函数。听起来好像很混乱,可能是执行代码 DLL 初始化代码会导致这些问题(可能该代码有一个旋转循环)。
      • 如果你想做这样的事情,你需要使用JNA来代替。但请注意,初始化代码可能仍然会让您感到困惑。
      • 奇怪的是,这个完全相同的调用在 Solaris 上工作。(没有 JNI)。我只是想将此调用移植到 Linux 并遇到此问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-01-16
      • 2013-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-16
      相关资源
      最近更新 更多