如何调试JNI堆损坏问题?

fer*_*olo 5 java java-native-interface

我有一个Java应用程序,通过JNI调用遗留应用程序的许多不同的本机方法.但是JVM在任何JNI调用之外的随机位置都会发生堆栈转储崩溃.有时它在GC期间崩溃,有时在课堂加载和其他地方崩溃.我怀疑一个或多个本机方法正在破坏JVM堆或其他一些数据结构.我需要知道这是哪个调用,所以我可以修复本机实现.

遗留应用程序是第三方DLL,我没有源代码或符号信息.为了使它可以从Java调用,我构建了一个使用JNI调用约定的包装器DLL.

完美的解决方案是扩展的JVM选项,它强制JVM在每次JNI调用后自动检查堆及其他数据结构的完整性.

你知道有什么可以帮助吗?

PS请不要告诉我在JVM和遗留应用程序之间构建套接字或管道层,因为我们的要求不允许这样做.这是关于错误检测,而不是架构设计.

fer*_*olo 5

因为我没有自己的答案而无法找到现成的解决方案,所以我最终在纯C++中构建了一个沙箱进程,以确定问题所在.我的Java应用程序使用ProcessBuilder实例化沙盒进程,然后使用stdin和stdout与它进行通信.而不是JVM,它是实际加载和调用遗留DLL的沙箱.然后我使用Microsoft的Application Verifier监视沙盒进程,它发现了内存损坏问题 - 有一个调用传递缓冲区小于预期.在确定之后,我只增加了在Java应用程序中用作缓冲区的byte []的长度,现在JVM可以直接调用DLL而不使用沙箱.

总的来说,我失去了将近10天,因为JVM在每次JNI调用后都没有选项来验证堆.但至少现在如果有人发现崩溃,我们可以使用沙箱快速调试它.