我试图找到我的
Java应用程序崩溃的原因.它实际上是由JNI调用本机库引起的JVM崩溃.
这是我在生成的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,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程序员,我不太习惯调试本机代码.所以我跟着tutorial on JVM crash analysis.
我按照指示:
> 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文件中停止工作.
为了找到有问题的源代码行,我现在可以做些什么?
编辑