哪个本机函数在JNI代码中导致EXCEPTION_ACCESS_VIOLATION?

Joh*_*n M 10 java-native-interface windbg bullet dumpbin libgdx

我正在尝试使用由libgdx Android Java开发框架(gdx-bullet)包装的子弹物理库,并在一段短暂的随机工作时间之后使JVM崩溃或"纯虚拟方法称为"崩溃.

其中一些生成hs_err_pidXXXX.log文件,通常包含:

#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0aa0c217, pid=7956, tid=7440
#
# JRE version: 7.0_05-b05
# Java VM: Java HotSpot(TM) Client VM (23.1-b03 mixed mode, sharing windows-x86 )
# Problematic frame:
# C  [gdx-bullet.dll+0x1c217]

Current thread (0x04af2800):  JavaThread "LWJGL Application" [_thread_in_native, id=7440, stack(0x04d70000,0x04dc0000)]

siginfo: ExceptionCode=0xc0000005, reading address 0x6572fc0f

Registers:
EAX=0x0073f370, EBX=0x0073f480, ECX=0x0073f484, EDX=0x6572fc07
ESP=0x04dbf3c0, EBP=0x04dbf400, ESI=0x0073f120, EDI=0x04dbf3f0
EIP=0x0aa0c217, EFLAGS=0x00010206

Instructions: (pc=0x0aa0c217)
0x0aa0c217:   ff 52 08 f3 0f 10 05 0c f0 ba 0a f3 0f 10 4c 24

Register to memory mapping:
EDX=0x6572fc07 is an unknown value

Stack: [0x04d70000,0x04dc0000],  sp=0x04dbf3c0,  free space=316k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [gdx-bullet.dll+0x1c217]
C  0x38cffed8

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  com.badlogic.gdx.physics.bullet.gdxBulletJNI.btDiscreteDynamicsWorld_stepSimulation__SWIG_1(JLcom/badlogic/gdx/physics/bullet/btDiscreteDynamicsWorld;FI)I+0
j  com.badlogic.gdx.physics.bullet.btDiscreteDynamicsWorld.stepSimulation(FI)I+7
Run Code Online (Sandbox Code Playgroud)

我被告知这可能是Java GC解除分配Java代码中不再引用的对象的问题,但仍需要子弹本机代码.

我检查了我的代码,但没有找到这种情况,这并不意味着它们不存在.我可以寻找更长的时间,但我想如果我继续这种方法,我需要学习如何自己调试这些情况.

所以我在gdx-bullet.dll上运行了dumpbin.exe,发现了以下内容:

6AB80000 image base (6AB80000 to 6BD4FFFF)
Run Code Online (Sandbox Code Playgroud)

然后我添加了0x6AB80000 + 0x1c217 = 0x6AB9C217并在dumpbin.exe反汇编中查找:

6AB9C206: 8B 10              mov         edx,dword ptr [eax]
6AB9C208: 89 6C 24 0C        mov         dword ptr [esp+0Ch],ebp
6AB9C20C: 89 7C 24 08        mov         dword ptr [esp+8],edi
6AB9C210: 89 4C 24 04        mov         dword ptr [esp+4],ecx
6AB9C214: 89 04 24           mov         dword ptr [esp],eax
6AB9C217: FF 52 08           call        dword ptr [edx+8]
6AB9C21A: F3 0F 10 05 0C F0  movss       xmm0,dword ptr ds:[6AD3F00Ch]
          D3 6A
6AB9C222: F3 0F 10 4C 24 30  movss       xmm1,dword ptr [esp+30h]
6AB9C228: 80 7E 2C 00        cmp         byte ptr [esi+2Ch],0
6AB9C22C: F3 0F 5C C8        subss       xmm1,xmm0
Run Code Online (Sandbox Code Playgroud)

哪个都很好,但是关于我被卡住的地方,因为我不知道[edx + 8]的位置.

我有使用的子弹的源代码(大约这一个).

我安装了windbg.exe并设法使userdump.exe生成一个javaw.dmp文件,但不确定要在一个文件中查找什么以及如何查找.我试图找出使用"r"命令什么是在rdx,但它是0x0而不是hs_err_pid文件,它是一些随机值.

我发现了一些构建脚本,但我怀疑我可以为它们添加"include debug info"标志,然后让它们以任何及时的方式工作.

我该怎么做才能找出出现问题的特定原生方法?

如果我知道那么我可以查看它的源代码,并了解我传递给它的错误参数或者GC已经取消分配了哪些对象.

Iro*_*uca 1

该指针可能太晚了,在您的情况下,由于访问已在本机代码中取消分配内存的指针而发生了访问冲突。在这种情况下,如果尝试写入该指针指向的内存,如果内存管理尚未重新分配已解除分配的块,则可能会实际工作几次。我在 Windows 中遇到过这种情况,最终程序在退出之前给出了堆溢出错误,并且从 Java 端抛出了上述错误。它之所以工作时间很短,是因为一旦内存块被解除分配,Windows不会立即分配它,而是当需要重新分配时,Windows会检查内存块的头字段,发现它是已损坏,因此出现堆溢出错误。

如果本机代码是您编写的,您可以添加跟踪并找到问题,在包装库中,也许您没有在 Java 端保留对库的引用,或者包装器中存在问题。