java - 通过 JNI 桥调用时楔形文字库崩溃

标签 java gdb java-native-interface shared-libraries

我正在编写一个Java应用程序,我从中调用(通过另一个库)来自 Cuneiform 的函数OCR 库。不幸的是,我在一个非常奇怪的地方发生了崩溃,我需要社区的建议。

程序在 RVERLINE_MarkLines() 的第一行代码处崩溃,从 RSL_SetImportData() 调用,在第一个代码位置(变量 lti 的初始化)。我已经检查了 gdb 中所有传递的变量:它们都有意义并且似乎有效。看起来堆栈已损坏,因为尝试重新整理 RVERLINE_MarkLines() 中的源代码行但没有成功。

相同输入数据的相同代码在从 C++ 代码(CPP CLI → 某个库 → Cuneiform 库)调用时工作正常,但在从 JVM 调用时(JVM → 某个库 → Cuneiform 库)会中断。

由于我是gdb的新手,也许有人可以给我提示,我怎样才能找出崩溃的原因?去哪里看、注意什么?

提前非常感谢。

堆栈跟踪:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7564b70 (LWP 416)]
RVERLINE_MarkLines (hCComp=0xb28a2708, hCPage=0xb28a28d0)
    at cuneiform-1.0.0.orig/cuneiform_src/Kern/rverline/src/root/vl_kern.cpp:120
120             LinesTotalInfo  lti = {0};  // Структура хранения линий
(gdb) bt
#0  RVERLINE_MarkLines (hCComp=0xb28a2708, hCPage=0xb28a28d0)
    at cuneiform-1.0.0.orig/cuneiform_src/Kern/rverline/src/root/vl_kern.cpp:120
#1  0xb3b7d727 in RSL_SetImportData (dwType=1, pData=0xb7559b50)
    at cuneiform-1.0.0.orig/cuneiform_src/Kern/rshelllines/src/rshelllines.cpp:332
#2  0xb3bdca96 in RLINE_LinesPass1 (hCPage=0xb28a28d0, hCCOM=0xb28a2708, phCLINE=0xb45a34fc, pgneed_clean_line=0xb45a3630, sdl=0,
    lang=0 '\000') at cuneiform-1.0.0.orig/cuneiform_src/Kern/rline/sources/newline.cpp:224
#3  0xb3b70bb2 in SearchNewLines (Image=0xb7559e1c)
    at cuneiform-1.0.0.orig/cuneiform_src/Kern/rstuff/sources/main/normalise.cpp:230
#4  0xb3b70d78 in Normalise (Image=0xb7559e1c)
    at cuneiform-1.0.0.orig/cuneiform_src/Kern/rstuff/sources/main/normalise.cpp:189
#5  0xb3b6d900 in RSTUFF_RSNormalise (Image=0xb7559e1c, vBuff=0xb31ba008, Size=500000, vWork=0xb318e008, SizeWork=180000)
    at cuneiform-1.0.0.orig/cuneiform_src/Kern/rstuff/sources/main/dll.cpp:352
#6  0xb458919a in Layout (lpdata=0x0) at cuneiform-1.0.0.orig/cuneiform_src/Kern/puma/c/partlayout.cpp:203
#7  0xb458b963 in PUMA_XFinalRecognition () at cuneiform-1.0.0.orig/cuneiform_src/Kern/puma/main/puma.cpp:590
...
#20 0xb77d5d0c in jni_CallStaticVoidMethod () from /usr/lib/jvm/java-6-sun-1.6.0.22/jre/lib/i386/client/libjvm.so
#21 0x08049b98 in JavaMain ()
#22 0xb7fc3955 in start_thread (arg=0xb7564b70) at pthread_create.c:300
#23 0xb7f35e7e in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:130

其他信息:

  • 平台 Linux x32
  • SUN JVM 1.6.0.22
  • 海湾合作委员会4.4.5

最佳答案

您的崩溃看起来像是堆栈耗尽的典型案例。

当你从 C++ 调用库时,你可能会使用主线程,它通常至少有 8MB。当您从 Java 调用它时,您是从 main 以外的某个线程调用它,该线程可能具有小得多的堆栈(例如 for Linux x32 default stack size is 320k – 这可能因不同平台和不同 JVM 实现而异)。

以下命令应该可以让您确认问题:

(gdb) p/x $esp
(gdb) shell cat /proc/<pid>/maps  # replace <pid> with the pid of crashing
                                  # thread, e.g. 416 above.

您可能会看到 $esp 指向无法访问的(防护)页面(具有 ---p 权限)。如果这是正确的,您必须创建使用具有更大堆栈的 OCR 库的线程,或者确保只能从主线程访问该库。您可以使用例如-Xss1024K JVM 参数(将为所有线程设置堆栈大小)或 -XX:MainThreadStackSize=1024K (仅为 HP-UX JVM 上的主线程设置堆栈大小)。

例如,$esp0xb755a000可以位于此内存段内(具有rw权限):

b7517000-b7565000 rwxp 00000000 00:00 0          [threadstack:0004d494]

关于java - 通过 JNI 桥调用时楔形文字库崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5043819/

相关文章:

java - 制作实例化列表时 <?> 是什么类型?

java - Spring JPA @OneToMany 参数值[]与预期类型不匹配

gdb - GDB 可以从 C 程序的核心转储中打印结构的大小吗?

c++ - gdb 启动但不逐行执行

spring-boot - 如何在 Spring Boot 应用程序中集成 JNI 共享库

java - 用户输入 Ctrl+Z 时终止 Java 程序

java - 在排序的 ArrayList 中查找项目的最快方法

ubuntu - gdb 无法识别正在运行的程序的格式

c++ - 如何用BSTR填充jobjectArray?

android - 如何在 Android 中构建没有 JNI 的共享库?