2009-11-19 23 views
7

Ứng dụng của tôi chủ yếu là Java nhưng, đối với một số tính toán nhất định, sử dụng thư viện C++. Môi trường của chúng tôi là Java 1.6 chạy trên RedHat 3 (sắp trở thành RedHat 5).Có thể gỡ lỗi các bãi lõi khi sử dụng Java JNI không?

Vấn đề của tôi là thư viện C++ không an toàn chỉ. Để giải quyết vấn đề này, chúng tôi chạy nhiều quy trình "công nhân" đơn luồng và cung cấp cho họ công việc để làm từ một Trình quản lý công việc trung tâm, cũng được viết bằng C++. Ứng dụng Java của chúng tôi gọi C++ Work Manager thông qua một sản phẩm của bên thứ ba.

Vì nhiều lý do, chúng tôi muốn viết lại Trình quản lý công việc và nhân viên C++. Tôi ủng hộ việc viết tất cả chúng trong Java, sử dụng JNI trong mỗi nhân viên để gọi thư viện C++.

Vấn đề chính là những gì xảy ra nếu lõi thư viện C++ đổ. Thật không may, điều này khá phổ biến và chúng tôi cần có thể xem dòng nào trong thư viện C++ của chúng tôi đã gây ra sự cố, ví dụ: bằng cách kiểm tra một backtrace trong một cái gì đó như GDB.

Đồng nghiệp của tôi tin rằng sẽ không thể phân tích các bãi lõi, bởi vì các công cụ như GDB không hiểu các tệp lõi do Java tạo ra.

Tôi hy vọng rằng chúng sai, nhưng tôi cần phải chắc chắn trước khi đẩy ý tưởng của mình hơn nữa.

Cách tốt nhất để phân tích kết xuất lõi được tạo ra từ Java/JNI là gì?

Trả lời

7

Có, có. Mỗi khi JVM đổ vỡ vì một SIGSEGV trong phần JNI, bạn sẽ nhận được một tệp có kết xuất lõi trong thư mục $ JAVA_HOME/bin. Nó thường có tên hs_err_PID.log.

Bạn có thể nhận thêm thông tin herehere. Here là câu hỏi về stackoverflow có liên quan.

+2

Cảm ơn Pablo. Bài viết của kohsuke thật tuyệt vời. Thật không may, nếu tôi nói với các đồng nghiệp của tôi rằng họ sẽ cần phải hiểu lắp ráp để khám phá dòng C++ gây ra lỗi seg, họ sẽ chạy một dặm. Tôi đang trên Linux và các tệp .so của tôi đã được biên dịch với cờ gỡ lỗi được bật. Có lẽ điều này sẽ làm cho quá trình dễ dàng hơn. –

+1

Xin lỗi, nhưng một tệp 'nhật ký' không liên quan gì đến coredump mà O.P đã hỏi. –

+0

Tôi đã tìm thấy các tệp hs_err_PID này trong thư mục/tmp. – Aman

2

Để lấy tệp lõi đọc vào gdb, bạn phải thêm máy ảo java vào nó. Đó là

gdb /usr/local/jdk1.8.0_66/bin/java core 

nó rất có thể sẽ cho bạn biết rằng không tìm thấy hàng triệu ký hiệu (bình thường, đây là biểu tượng JVM). Tuy nhiên, cuộc gọi JNI bị lỗi có thể xuất hiện trong stacktrace của bạn nếu bạn nhập 'bt'. Một ví dụ, trong trường hợp của tôi, nơi tôi có sự cố trong thư viện gốc tôi đã viết, là:

(gdb) bt 
#0 0x00007fd61dfcd107 in __GI_raise ([email protected]=6) 
    at ../nptl/sysdeps/unix/sysv/linux/raise.c:56 
#1 0x00007fd61dfce4e8 in __GI_abort() at abort.c:89 
#2 0x00007fd61d8d3795 in os::abort(bool)() 
    from /usr/local/jdk1.8.0_66/jre/lib/amd64/server/libjvm.so 
#3 0x00007fd61da71e23 in VMError::report_and_die()() 
    from /usr/local/jdk1.8.0_66/jre/lib/amd64/server/libjvm.so 
#4 0x00007fd61d8d8fbf in JVM_handle_linux_signal() 
    from /usr/local/jdk1.8.0_66/jre/lib/amd64/server/libjvm.so 
#5 0x00007fd61d8cf753 in signalHandler(int, siginfo*, void*)() 
    from /usr/local/jdk1.8.0_66/jre/lib/amd64/server/libjvm.so 
#6 <signal handler called> 

6 khung đầu tiên tất cả đều liên quan đến chính bản thân sự cố. Một tín hiệu đã bị bắt và gửi đi. Và mặc dù chúng tôi không biết các chức năng chính xác, nó không quan trọng. Bắt đầu từ khung 7, chúng tôi đang ở trong thư viện JNI, chúng tôi đã viết. Và nếu nó vẫn còn các biểu tượng gắn liền bạn sẽ thấy chúng.

#7 0x00007fd5ff43bf7e in FftResampler::resample(Complex const*, int) 
    () 
    from /I/home/werner/BpmDj/NextGen/Beta/Desktop/test/libzathras-46703-64.so 
#8 0x00007fd5ff43ddcf in TimeStretcher::rescaleEnvelopeSlow(PeakMap const*, Peak*)() 
    from /I/home/werner/BpmDj/NextGen/Beta/Desktop/test/libzathras-46703-64.so 
#9 0x00007fd5ff43e4a5 in TimeStretcher::transferPeak(Frame*, Frame*) 
    () 
    from /I/home/werner/BpmDj/NextGen/Beta/Desktop/test/libzathras-46703-64.so 
#10 0x00007fd5ff43e679 in TimeStretcher::transferPeaks(Channel*)() 
    from /I/home/werner/BpmDj/NextGen/Beta/Desktop/test/libzathras-46703-64.so 
#11 0x00007fd5ff43eb3a in TimeStretcher::putStereo(float const*, int) 
    () 
    from /I/home/werner/BpmDj/NextGen/Beta/Desktop/test/libzathras-46703-64.so 
#12 0x00007fd5ff43edbf in TimeStretcher::processStereo(float const*, int, float*)() 
    from /I/home/werner/BpmDj/NextGen/Beta/Desktop/test/libzathras-46703-64.so 
#13 0x00007fd5ff43b45d in Java_org_yellowcouch_bpmdj_mixedit_audio_JavaTimeStretcher_processStereo() 
    from /I/home/werner/BpmDj/NextGen/Beta/Desktop/test/libzathras-46703-64.so 

Và từ khung 14 trở đi, chúng tôi trở lại vùng đất java.

#14 0x00007fd6097a29e1 in ??() 
#15 0x00007fd5d6ee6580 in ??() 
#16 0x00000000853f53e8 in ??() 
#17 0x00000000d803c340 in ??() 
#18 0x00000000d80564e8 in ??() 
#19 0x00007fd61e773609 in _L_unlock_554() 
    from /lib/x86_64-linux-gnu/libpthread.so.0 

Vì vậy, bạn thấy không hoàn toàn không thể lấy một số thông tin ra khỏi tệp lõi thông qua gdb. Chỉ cần đừng quên thêm jvm làm đối số đầu tiên cho nó.

Có thể gdb không tìm thấy chính thư viện gốc. Trong trường hợp đó, bạn có thể muốn tải các ký hiệu theo cách thủ công như sau:

gdb> symbol-file libzathras-46703-64.do đó

Nếu bạn muốn biết thêm thông tin, bạn có thể muốn biên dịch mã c/C++ của bạn với thông tin gỡ lỗi được bật. Nói chung với trình biên dịch mingw và gcc bạn thêm một -g vào các tùy chọn dòng lệnh. Điều này sẽ cung cấp cho bạn thông tin sau, bao gồm số dòng và như vậy.

#7 FftResampler::resample ([email protected]=0x7f4bf8f36100, 
    [email protected]=0x7f4bf8ed1ea0, n=<optimized out>) 
    at timestretcher.cpp:347 
#8 0x00007f4c51605dcf in TimeStretcher::rescaleEnvelopeSlow (
    this=0x7f4bf8ec1e10, table=0x7f4bf90f4c20, borders=0x7f4bf8fd27a0) 
    at timestretcher.cpp:878 
#9 0x00007f4c516064a5 in TimeStretcher::transferPeak (
    [email protected]=0x7f4bf8ec1e10, 
    [email protected]=0x7f4bf8fde6f0, 
    [email protected]=0x7f4bf8fb2650) at timestretcher.cpp:718 
#10 0x00007f4c51606679 in TimeStretcher::transferPeaks (
    [email protected]=0x7f4bf8ec1e10, 
    [email protected]=0x7f4bf8ec9e90) at timestretcher.cpp:687 
#11 0x00007f4c51606b3a in TimeStretcher::putStereo (
    [email protected]=0x7f4bf8ec1e10, [email protected]=0x7f4bf8eb9e00, 
    [email protected]=-1395) at timestretcher.cpp:1483 
#12 0x00007f4c51606dbf in TimeStretcher::processStereo (
    [email protected]=0x7f4bf8ec1e10, [email protected]=0x7f4bf8eb9e00, 
    [email protected]=-1395, out=0x7f4bf90f4c60) 
    at timestretcher.cpp:1567 
#13 0x00007f4c5160345d in Java_org_yellowcouch_bpmdj_mixedit_audio_JavaTimeStretcher_processStereo (env=0x7f4bf90f71f8, obj=<optimized out>, 
    handle=139964275465728, in=0x7f4bed136468, inIdx=<optimized out>, 
    time=-1395, out=0x7f4bed136480) at timestretcher-jni.cpp:69 
+0

cũng đừng quên bạn có thể sử dụng 'addr2line' với địa chỉ từ bãi chứa để lấy dòng mã chính xác gây ra sự cố. – Shark

Các vấn đề liên quan