在 Java JNA 调用的 dll 中分配内存错误

Allocate memory error in dll called by Java JNA

我尝试在 Java 中使用 JNA 集成 DLL。 DLL 分配大量内存(~600MB)。 库被编译为 32 位版本,所以我需要使用 32 位 JVM。

JVM 出现致命错误

 EXCEPTION_UNCAUGHT_CXX_EXCEPTION (0xe06d7363) at pc=0x772bd928, pid=7976, tid=2444

有详细信息

siginfo: ExceptionCode=0xe06d7363, ExceptionInformation=0x19930520 0x02dce184 0x6a3853d8 

并堆叠

Stack: [0x023d0000,0x02dd0000],  sp=0x02dce0d0,  free space=10232k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [KERNELBASE.dll+0xbd928]
C  [MSVCR120D.dll+0x120b86]
C  [MSVCR120D.dll+0x12c2a1]
C  [face_analysis_libD.dll+0x1157dc]  operator new[]+0xc
C  [face_analysis_libD.dll+0xea995]  Mat<float>::setSize+0xa5
C  [face_analysis_libD.dll+0xe904e]  Recognizer::initialize+0x9e
C  [face_analysis_libD.dll+0xb2bf9]  Analyser::initializeAnalyser+0x1c9

应用程序以参数启动

-Xmx1300m -Xms1300m -Xss10m -XX:MaxDirectMemorySize=3g -XX:+PrintHeapAtGC

问题可能出在 JVM 上的某些内存限制(该库与 C# 配合得很好)。也许有人有类似的问题,可以帮助我找到如何在 32 位 JVM 中 运行 这个库的解决方案。

32 位应用程序通常限制为 2GB 的虚拟地址 space。假设您使用的是 64 位 windows,如果二进制文件是使用 largeaddressaware 标志构建的,则这可以扩展到 4GB。我觉得32bit的java.exe还没有,虽然我自己没测试过

因此,如果 JVM 已经占用了 1.3G 的堆内存、线程堆栈和其他非堆数据结构的额外内存,那么留给 dll 进行分配的空间就很少了。如果它随后需要进行大量连续分配,这可能会失败并引发 C++ 异常。

您的选择可能是:

  • 减少堆大小
  • 改用该库的 64 位版本
  • 查看将二进制文件标记为 largeaddressaware 是否有帮助,有工具可以做到这一点