问题描述
我一直在写一个小的java应用程序(我的第一个!),目前只做了一些事情。 目前,它运行Main类,它启动一个gui类(我编写的一个扩展JFrame的类,只包含一个JTextArea),一个通过大约40kb的BufferedInputStream加载本地文件的类,以及一个从一个类加载一个条目的类。 Java属性文件。
一切都运行得非常好,然而,我正在看着Windows任务管理器,我注意到一些让我感到奇怪的东西。 当我启动应用程序时,RAM使用量会在加载本地文件时跳转到大约40MB,并从中提取一些值以显示在JTextArea中,这对我来说是正常的,因为JVM,Java基类等等。但是,当应用程序完成加载文件时,它只是闲置,因为我目前还没有做任何其他事情。 当它处于空闲状态时,只要窗口处于活动状态,应用程序的内存使用量就会每秒开始上升10-20kb。 这让我很奇怪。 如果我点击另一个程序使这个程序成为非活动窗口,内存仍会上升,但速度要慢得多(每3-5秒约10kb)。
我没有测试看它会走多远,但这让我觉得非常奇怪。 这是正常的Java行为吗? 我想我的代码可能会泄漏内存,但我不确定如何。 我确实关闭了我正在使用的BufferedInputStream,我看不出还有什么会导致这种情况。
如果我的解释没有意义,我很抱歉,但我很感激任何人可能有的见解和/或指示。
更新:
根据建议,我基本上将我的应用程序剥离到Main类,它只调用gui类。 gui类只扩展JFrame并设置窗口大小,关闭操作和可见属性。 随着这些变化,内存仍然以10-20kb的速度增长,但速度较慢。 这与我收到的其他建议相结合,让我相信这只是Java。 如果我发现其他任何有趣的东西,我将继续玩它,让大家都知道。
1楼
尝试使用jconsole而不是Windows任务管理器监视堆使用情况:
- 使用-Dcom.sun.management.jmxremote选项启动您的应用程序,例如
java -Dcom.sun.management.jmxremote -jar myapp.jar
-
从命令行启动
jconsole
,并连接到您在上一步中启动的java进程的本地pid。 - 单击内存并查看堆内存(默认显示)
如果你观看一段时间,随着时间的推移,你可能会得到一个“锯齿”的模式,但是当垃圾收集器运行时,它会急剧下降。 您可以尝试通过单击如此标记的按钮来“建议”垃圾收集。
当你这样做时,内存使用量是否下降到相同的最低水平,或者是几分钟内总体最小值的增加? 如果最小使用量增加,则会出现内存泄漏。 如果它总是返回到相同的最低水平,那么你没事。
2楼
祝贺你的第一款应用!
现在,有几件事要考虑。
首先,Windows任务管理器不是了解vm增长速度的重要资源。
相反,您应该在控制台中监视垃圾收集统计信息(使用-verbose:gc
命令行参数)。
其次,如果您担心潜在的泄漏和虚拟机的增长,那里有许多优秀的剖析器易于使用,可以帮助您诊断内存问题。
查看这 查看一些分析器选项。
3楼
恭喜您的第一个Java应用程序!
Java应用程序在虚拟机中运行。 操作系统为虚拟机分配了固定数量的内存,通常为512 MB。 只要应用程序使用少于512 MB,垃圾收集器就不会启动并开始搜索“死”内存块。 可以在大多数操作系统中修改JVM内存限制。 例如,尝试将内存限制切换为32 MB。
4楼
这是正常的Java行为吗?
没有。
我想我的代码可能会泄漏内存
这绝对是原因。 请发布您的源代码,否则无法进一步诊断。
我注意到您正在使用Swing,请确保使用invokeLater(Runnable)
方法在中启动JFrame
。
如果您正在使用任何类型的集合,请确保在完成后clear
它们。
由于您正在执行某些文件IO,因此请确保在完成IO操作后关闭所有涉及的操作。
如果您正在使用任何事件侦听器,请记住在不再需要时显式删除事件侦听器。
你可以尝试的一件事是试验。 拿你的应用程序并删除文件IO,看看会发生什么。 内存使用量是否仍像以前一样攀升? 现在将您的应用程序重新设置为正常,并删除文本区域 - 内存是否仍像以前一样爬升? 等等。这将帮助您确定源是什么,并且您可以集中精力在那里。 通过这样做,你很可能会发现你所追求的是什么。
另一个有用的诊断工具是在特定时间点使用System.gc()
,通常是在繁重的代码块之后。
这将告诉JVM在执行中的该点执行垃圾收集,而不是在内存消耗确定的另一个时间执行垃圾收集。
这将帮助您考虑应用程序内存使用量的任何周期性波动。
如果失败了,你总是可以使用内存分析器。 如果您使用的是Netbeans IDE,那么它就是内置的。 对于Eclipse,有几个插件可以执行分析。
5楼
这是正常的。 一些背景计算可能会留下死对象,JVM并不急于清理。 当接近max mem时,最终它们将被垃圾收集。
让你的程序一夜之间运行,你的机器不会爆炸。