我的Java应用程序似乎有内存泄漏。这是我第一次处理类似的事情。我不是使用纯Java而是使用JNA来使用user32功能。 我注意到,当我的程序运行较长时间(如一小时)时,其进程所需的内存不断增长。当我开始它时,它就像100Mb,最终在一小时后超过1Gb。
我注意到这是使用Windows任务管理器。当我开始研究这个时,我使用了像visualvm和JProfiler这样的分析器。两者都向我展示了大约150mb的堆使用量和大约20mb的PermGen空间,而Windows任务管理器清楚地告诉我它耗尽了大约1Gb。所以我认为问题必须在本机堆中,visualvm和JProfiler似乎都无法访问/配置文件。我创建了堆转储和内存快照,并使用visualvm和MAT对它们进行了分析。最大的物体(以及它们保留的尺寸)从未输过4Mb - 我根本就不是专家,但这对我来说似乎并不是非常漏洞/不太大。此外,当我手动收集垃圾(使用分析器)时,使用的Java堆按预期变小,但过程的总体消耗保持在1Gb。这一发现也使我得出结论,问题不在Java堆空间内。
所以我认为JNA调用导致了这个问题。但不幸的是我不知道如何解决这个问题,因为我不能简单地不使用JNA。我阅读了大量有关内存泄漏的清晰度,其中大多数与jave相关的内容几乎总是忽略本机堆。那些没有的(例如oracle文章)告诉我,我不能简单地使用其中一种原生分析方法,因为它们会误解java代码并导致错误的结论。 Oracle建议" libumem.so",但这似乎只适用于solaris系统。
所以我的整体问题是 - 有人可以给我任何关于做什么的暗示吗?我可以使用哪些工具?
但也许问题只是我没有正确使用JNA。根据这个: https://groups.google.com/forum/#!topic/jna-users/Xy7Sm8Fb-Gc 从我从stackoverflow的几个文本片段中读到和理解的内容,互联网上的jna文档和随机关键词是JNA将释放它分配的内存,并且java端的分配内存将被垃圾收集。所以当我做以下事情时:
//I want to get text (as a String) of a handle
public static String getTextOfHWND(HWND hwnd)
{
//allocate the space for the string
byte[] windowText = new byte[512];
//let user32 method fill me the byte array with the needed information
User32.INSTANCE.SendMessageA(hwnd, WM_GETTEXT, 100, windowText);
//let Native convert this to a String I can use in Java
String whatWasFound = Native.toString(windowText);
return whatWasFound;
}
..." byte [] windowText"变量(为它分配的内存)应该由GC释放,同样应该对我得到的字符串有效(" whatWasFound")。那是对的吗?在这个例子中,我需要手动释放一些东西吗?我可以看到Native为Buffers提供了一个免费的方法(但不幸的是没有为数组提供)。在本机方面发生了什么,是在那里分配的东西,它是否在之后发布?
感谢任何帮助。