我有一个用 C 编写的应用程序,它生成一个 JVM 并使用 JNI 与 Java 应用程序交互。我通过 Process Explorer 的内存占用达到 1GB 并且内存不足。现在据我所知,它应该能够达到 2GB。我相信的一件事是 JVM 正在使用的内存在 Process Explorer 中不可见。我的 xmx 设置为 256,我添加了一些语句来观察 java 端内存,它在 256 处达到峰值,而 GC 正在完成它的工作,这一切都很好。所以我的问题是,其他 700+ MB 的消耗在哪里?那里有 Java/JNI/C 内存专家吗?
6 回答
尝试使用 C 语言的测试应用程序,它不会产生 JVM,而是尝试分配越来越多的内存。查看测试应用程序是否可以达到 2 GB 的障碍。
JNI 代码中可能存在泄漏。
记住,一旦你完成了任何对象引用,就使用 (*jni)->DeleteLocalRef()。如果您使用任何本机 C 缓冲区来创建新的 Java 对象,请确保在创建对象后释放它们。查看 JNI 规范以获取更多指南。
根据您使用的 VM,您可能能够打开 JNI 检查。例如,在 IBM JDK 上,您可以指定“-Xcheck:jni”。
好吧,感谢您的所有帮助,尤其是@alexander,我发现Java Heap 正在使用通过Process Explorer 不可见的所有额外内存。事实上,通过我运行的其他测试,JVM 的内存消耗包含在我从 Process Explorer 中看到的内容中。所以堆占用了大量的内存,我将不得不对此做更多的研究,也许会问一个单独的问题。
编写一个 C 测试工具并使用 valgrind/alleyoop 检查 C 代码中的泄漏,同样使用 java jvisualvm 工具。
C 和 JNI 代码也可以分配内存(malloc/free/new/etc),这在 VM 的 256m 之外。xMX 仅限制 VM 将自行分配的内容。根据您在 C 代码中分配的内容,以及在内存中加载的其他内容,您可能无法达到 2GB,也可能无法达到。
如果您说是 Windows 进程内存不足而不是 JVM,那么我最初的猜测是您可能从 JVM 调用了一些(您自己的)本机方法,而这些本机方法会泄漏内存。所以,我同意@John Gardner 的观点。