Я пытаюсь найти причину сбоя в моем приложении Java. На самом деле это сбой JVM, вызванный вызовом нативной библиотеки через JNI.
Вот что я вижу в сгенерированном hs_err_pidxxxx.log
:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_INT_DIVIDE_BY_ZERO (0xc0000094) at pc=0x4fa19409, pid=1456, tid=4068
#
# JRE version: 6.0_30-b12
# Java VM: Java HotSpot(TM) Client VM (20.5-b03 mixed mode windows-x86 )
# Problematic frame:
# C [JCustomOpc.dll+0x9409]
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
--------------- T H R E A D ---------------
Current thread (0x4ab1c400): JavaThread "opc_service" daemon [_thread_in_native, id=4068, stack(0x4f200000,0x4f250000)]
siginfo: ExceptionCode=0xc0000094
Registers:
EAX=0x00000000, EBX=0x00000000, ECX=0x4f24f958, EDX=0x80000000
ESP=0x4f24f93c, EBP=0x4f24f940, ESI=0x4f24f9a4, EDI=0x52d396f4
EIP=0x4fa19409, EFLAGS=0x00010286
Top of Stack: (sp=0x4f24f93c)
0x4f24f93c: 4f24f98a 4f24f970 4fa1968a 52220000
0x4f24f94c: 5042f418 4f24f9a4 4b1ba6e8 00000004
0x4f24f95c: 52d396f4 4ab1c528 4f24f9a8 4f24f9a6
0x4f24f96c: 4f24f9a4 4f24f98c 4fa197cc 4f24f98a
0x4f24f97c: 52220000 5042f418 00000036 4f24f9a8
0x4f24f98c: 4ab33d1c 4fa6388f 52220000 5042f418
0x4f24f99c: 4ab1c528 4ab33d24 00000008 6d92f61f
0x4f24f9ac: 4ab1c528 4ab33d1c 00000022 0000000a
Instructions: (pc=0x4fa19409)
0x4fa193e9: db 89 c1 dd 45 08 d8 8b 88 21 a7 4f 83 ec 08 df
0x4fa193f9: 3c 24 9b 58 5a 09 d2 79 11 f7 da f7 d8 83 da 00
0x4fa19409: f7 b3 8c 21 a7 4f f7 d8 eb 06 f7 b3 8c 21 a7 4f
0x4fa19419: 05 5a 95 0a 00 89 11 89 41 04 5b 5d c2 08 00 55
Register to memory mapping:
EAX=0x00000000 is an unknown value
EBX=0x00000000 is an unknown value
ECX=0x4f24f958 is pointing into the stack for thread: 0x4ab1c400
EDX=0x80000000 is an unknown value
ESP=0x4f24f93c is pointing into the stack for thread: 0x4ab1c400
EBP=0x4f24f940 is pointing into the stack for thread: 0x4ab1c400
ESI=0x4f24f9a4 is pointing into the stack for thread: 0x4ab1c400
EDI=0x52d396f4 is an unknown value
Stack: [0x4f200000,0x4f250000], sp=0x4f24f93c, free space=318k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [JCustomOpc.dll+0x9409]
C [JCustomOpc.dll+0x968a]
C [JCustomOpc.dll+0x97cc]
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
J javafish.clients.opc.JOpc.getDownloadGroupNative()Ljavafish/clients/opc/component/OpcGroup;
J fr.def.iss.vd2.mod_opc_service.JEasyFacade.getPossiblyChangedGroups()Ljava/util/Collection;
J fr.def.iss.vd2.mod_opc_service.OpcServiceImpl.updateState()V
j fr.def.iss.vd2.mod_opc_service.OpcServiceImpl.access$3000(Lfr/def/iss/vd2/mod_opc_service/OpcServiceImpl;)V+1
j fr.def.iss.vd2.mod_opc_service.OpcServiceImpl$5.handlOpcEvents()V+103
j fr.def.iss.vd2.mod_opc_service.OpcServiceImpl$Worker.run()V+156
j java.lang.Thread.run()V+11
v ~StubRoutines::call_stub
Итак, это показывает, что в JCustomOpc.dll
есть деление на ноль. JCustomOpc.dll
- сторонняя библиотека, написанная на Delphi и скомпилированная нашей командой с Borland Delphi pro 7.0. Сейчас я пытаюсь найти, где в исходном коде Delphi происходит это деление на ноль.
Я в основном программист на Java, и мне неудобно отлаживать нативный код. Итак, я следовал учебнику по анализу сбоев JVM .
Я следовал инструкциям:
> dumpbin /headers JCustomOpc.dll
...
OPTIONAL HEADER VALUES
10B magic #
2.25 linker version
60800 size of code
12400 size of initialized data
0 size of uninitialized data
616A8 RVA of entry point
1000 base of code
62000 base of data
400000 image base
...
Итак, база изображения 400000, и в соответствии с руководством я ожидаю, что инструкция деления будет со смещением 409409.
Давайте посмотрим на это с дизассемблером:
> dumpbin /exports /disasm JCustomOpc.dll
...
004093E0: C3 ret
004093E1: 8D 40 00 lea eax,[eax]
004093E4: 55 push ebp
004093E5: 8B EC mov ebp,esp
004093E7: 53 push ebx
004093E8: 31 DB xor ebx,ebx
004093EA: 89 C1 mov ecx,eax
004093EC: DD 45 08 fld qword ptr [ebp+8]
004093EF: D8 8B 88 21 46 00 fmul dword ptr [ebx+00462188h]
004093F5: 83 EC 08 sub esp,8
004093F8: DF 3C 24 fistp qword ptr [esp]
004093FB: 9B wait
004093FC: 58 pop eax
004093FD: 5A pop edx
004093FE: 09 D2 or edx,edx
00409400: 79 11 jns 00409413
00409402: F7 DA neg edx
00409404: F7 D8 neg eax
00409406: 83 DA 00 sbb edx,0
00409409: F7 B3 8C 21 46 00 div eax,dword ptr [ebx+0046218Ch]
0040940F: F7 D8 neg eax
00409411: EB 06 jmp 00409419
00409413: F7 B3 8C 21 46 00 div eax,dword ptr [ebx+0046218Ch]
00409419: 05 5A 95 0A 00 add eax,0A955Ah
0040941E: 89 11 mov dword ptr [ecx],edx
00409420: 89 41 04 mov dword ptr [ecx+4],eax
00409423: 5B pop ebx
00409424: 5D pop ebp
00409425: C2 08 00 ret 8
...
409409 - это действительно инструкция div.
Я очень мало знаю о сборке, но этот код, похоже, манипулирует значением с плавающей запятой и производит целочисленное деление. Я искал исходный код Delphi, но не нашел ничего похожего на арифметическую операцию.
Я почти уверен, что есть надежный способ определить, какая функция Delphi соответствует этой части сборки, но я не знаю, как это сделать. У меня есть весь исходный код этой DLL, и у меня есть полный контроль над тем, как его скомпилировать.
Исходники delphi (.pas) генерируют скомпилированные файлы (.dcu), возможно, эти файлы могут помочь в моей проблеме, но я не знаю, что с ними делать. Есть опция компоновщика, чтобы создать файл карты. Он создает файл JCustomOpc.map, который представляет собой текстовый файл, содержащий множество символов и смещений. Но смещения не соответствуют ничему около 9404.
Я должен добавить, что этот сбой происходит на машине нашего клиента, но не воспроизводим на наших машинах. Кроме того, на самом деле невозможно выполнить некоторые тесты на компьютере клиента, поэтому я зациклен на работе только с hs_err_pid file
.
Что я могу сделать сейчас, чтобы найти проблемную строку источника?
Редактировать
Вот созданный файл подробной карты .