我有一个Java应用程序,它通过JNI调用遗留应用程序的许多不同的本机方法。但是JVM在任何JNI调用之外的随机位置都会发生堆栈转储崩溃。有时它在GC期间崩溃,有时在课堂加载和其他地方崩溃。我怀疑一个或多个本机方法正在破坏JVM堆或其他一些数据结构。我需要知道这是哪个调用,所以我可以修复本机实现。
遗留应用程序是第三方DLL,我没有源代码或符号信息。为了使它可以从Java调用,我构建了一个使用JNI调用约定的包装器DLL。
完美的解决方案是扩展的JVM选项,它强制JVM在每次JNI调用后自动检查堆及其他数据结构的完整性。
你知道有什么可以帮助吗?
P.S。请不要告诉我在JVM和遗留应用程序之间构建套接字或管道层,因为我们的要求不允许这样做。这是关于错误检测,而不是架构设计。
答案 0 :(得分:5)
因为我没有自己的答案而无法找到现成的解决方案,所以我最终在纯C ++中构建了一个沙盒进程,以确定问题所在。我的Java应用程序使用ProcessBuilder实例化沙盒进程,然后使用stdin和stdout与它进行通信。而不是JVM,它是实际加载和调用遗留DLL的沙箱。然后我使用Microsoft的Application Verifier监视沙盒进程,它发现了内存损坏问题 - 有一个调用传递缓冲区小于预期。在确定之后,我只增加了在Java应用程序中用作缓冲区的byte []的长度,现在JVM可以直接调用DLL而不使用沙箱。
总的来说,我失去了将近10天,因为JVM在每次JNI调用后都没有选项来验证堆。但至少现在如果有人发现崩溃,我们可以使用沙箱快速调试它。