Java native interface 在JNI代码中,哪个本机函数导致异常访问冲突?

Java native interface 在JNI代码中,哪个本机函数导致异常访问冲突?,java-native-interface,windbg,libgdx,bullet,dumpbin,Java Native Interface,Windbg,Libgdx,Bullet,Dumpbin,我正试图使用libgdx安卓Java开发框架包装的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.

我正试图使用libgdx安卓Java开发框架包装的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
我被告知这可能是Java GC解除分配Java代码中不再引用的对象的问题,但bullet本机代码仍然需要该对象

我检查了我的代码,但是没有发现这样的情况,这并不意味着它们不存在。我可以期待更长的时间,但我认为如果我继续使用这种方法,我需要学习如何自己调试这种情况

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

6AB80000 image base (6AB80000 to 6BD4FFFF)
然后我添加了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
这一切都很好,但关于我被困在哪里,因为我不知道什么位于[edx+8]

我有bullet的源代码

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

我找到了一些,但不知何故,我怀疑我是否可以添加“includebugginfo”标志,然后让它们以任何及时的方式工作

我能做些什么来找出哪个特定的本机方法有问题?


如果我知道这一点,那么我就可以查看它的源代码,了解我传递给它的是什么坏参数,或者GC取消分配了它需要的什么对象。

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


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

您是否考虑到RVA!=弗吉尼亚州?您需要一个.map文件用于手动查找,或者需要一个正确的PDB文件用于WinDbg执行的自动查找。我肯定会首先提出这个建议。问题是您的构建可能仍然不同,例如调试和发布。否则,最后的办法是学习RCE并使用类似IDA或OllyDbg的东西将反汇编映射到源代码。相当麻烦的方法。不,我上一次编程汇编是在15年前,那是真实模式,我几乎不能理解“RVA!=VA”的概念。我想我运气不好。此时[edx+8]是无效的,但通过查看[edx+8]以前的有效值,您可能可以了解被调用的内容。在使用
bu gdx bullet+0x1c217
重新生成崩溃之前,您可以通过在gdx bullet.dll+0x1c217处设置断点来完成此操作。这将在call指令处中断,然后您可以发出
t
以进入正在调用的函数。现在,如果call指令是用来调用太阳底下的所有东西,那么这种技术就没有用了。但是如果是因为打电话告诉funcs子弹必须飞多远,那你就很幸运了。马克,这是一个有趣的想法,下次情况出现时我会试试。谢谢不确定这是否有帮助,但您可以尝试附加一个调试器,并将其设置为此错误的第二次机会异常,然后以这种方式进行实时调试,这通常会让您更好地了解机器的状态。